【发布时间】:2019-09-19 15:25:57
【问题描述】:
我有一个自定义类,它继承自 Python 的内置 datetime.date 类:
# types.py
from datetime import date
class Date(date):
def __new__(cls, *args, isExceptional: bool = None, **kwargs):
if len(args) == 1 and isinstance(args[0], date):
self = super().__new__(
cls, args[0].year, args[0].month, args[0].day, **kwargs)
else:
self = super().__new__(cls, *args, **kwargs)
if isExceptional is not None:
self._isOff = True if self.isoweekday() in (6, 7) else False
if isExceptional:
self._isOff = not self._isOff
else:
self._isOff = None
return self
@property
def isOff(self):
return self._isOff
@isOff.setter
def isOff(self, value: bool):
if self._isOff is not None:
raise AttributeError(
"'isOff' can be set only when it is currently undefined, i.e. None"
)
else:
self._isOff = value
总而言之,Date 类似于内置的date,还有一个附加的_isOff 属性及其访问器。它的构造函数接受标准 date 对象或原始 date 构造函数可接受的任何参数作为参数,以及一个额外的仅限关键字的参数,以操纵 _isOff 值。
这个类基本上可以工作,因为
test = Date(2019, 9, 15)
print(test.isoformat(), "; isOff:", test.isOff)
test = Date(2019, 9, 15, isExceptional=False)
print(test.isoformat(), "; isOff:", test.isOff)
test = Date(2019, 9, 15, isExceptional=True)
print(test.isoformat(), "; isOff:", test.isOff)
给我:
2019-09-15 ; isOff: None
2019-09-15 ; isOff: True
2019-09-15 ; isOff: False
另一方面,我有一个 MariaDB 表:
CREATE TABLE `date` (
`date` DATE NOT NULL,
`isOff` BIT(1) NOT NULL DEFAULT b'0',
PRIMARY KEY (`date`)
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB
;
我想在它们之间做 SQLAlchemy 映射。我无法弄清楚“声明式”的方式,所以我尝试了经典映射,如下所示:
# orm.py
import sqlalchemy as ORM
date = ORM.Table(
'date',
ORM.MetaData(),
ORM.Column('date', ORM.Date, primary_key=True),
ORM.Column('isOff', ORM.Boolean)
)
# types.py, after the Date class definition
from . import orm
from sqlalchemy.orm import mapper
mapper(Date, orm.date)
以上,test = Date(2019, 9, 15) 给我
Traceback (most recent call last):
File "c:\users\user\appdata\local\programs\python\python37-32\Lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "c:\users\user\appdata\local\programs\python\python37-32\Lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "D:\data\work\newsys\newsys\types.py", line 39, in <module>
test = Date(2019, 9, 15)
TypeError: __init__() takes 1 positional argument but 4 were given
我猜错误消息中提到的__init__() 来自SQLAlchemy 的映射机制,因为我的类和标准的date 类中都没有定义__init__()。除此之外,我无法弄清楚发生了什么......那个“1位置参数”应该是什么以及作为那些4提供的?
如何在对我的 Date 类进行最少修改的情况下映射它们?
【问题讨论】:
标签: python python-3.x inheritance sqlalchemy