我想存储在我的代码中使用的实体并避免多次出现。因此,我的想法是使用一种__init__方法来收集我的类的主要数据,然后使用一种__post_init__方法从我的类对象中计算 id。这是代码:
class Worker(Base):
__tablename__='worker'
id = Column(Integer,primary_key=True)
profile=Column(String(100),nullable=False)
useragent=Column(String(100),nullable=False)
def __init__(self,useragent,profile):
""" specify the main information"""
print('init')
self.profile= profile
self.useragent=useragent
def __post_init__(self):
""" compute an id based on self, the worker"""
self.id=id(self)
print('dans post init')
Run Code Online (Sandbox Code Playgroud)
在此示例中,__init__可以使用该方法,但它不会__post_init__像我们对 dataclass 所期望的那样运行该方法,例如。
如何在执行该方法后立即运行此__init__方法?
小智 7
我使用以下方法实现了类似的行为__init_subclass__:
class Parent:
def __init_subclass__(cls, **kwargs):
def init_decorator(previous_init):
def new_init(self, *args, **kwargs):
previous_init(self, *args, **kwargs)
if type(self) == cls:
self.__post_init__()
return new_init
cls.__init__ = init_decorator(cls.__init__)
def __post_init__(self):
pass
class Child(Parent):
def __init__(self):
print('Child __init__')
def __post_init__(self):
print('Child __post_init__')
class GrandChild(Child):
def __init__(self):
print('Before calling Child __init__')
Child.__init__(self)
print('After calling Child __init__')
def __post_init__(self):
print('GrandChild __post_init__')
child = Child()
# output:
# Child __init__
# Child __post_init__
grand_child = GrandChild()
# output:
# Before calling Child __init__
# Child __init__
# After calling Child __init__
# GrandChild __post_init__
Run Code Online (Sandbox Code Playgroud)
该__post_init__方法是特定于dataclasses库的,因为类__init__上的方法dataclass是生成的,覆盖它首先会完全破坏生成它的目的。
另一方面,SQLAlchemy 提供__init__了基础模型类的实现(使用 为您生成declarative_base())。设置默认值后,您可以通过super().__init__(). 考虑到SQLAlchemy-provided__init__方法只接受关键字参数:
def __init__(self, useragent, profile):
"""specify the main information"""
id = generate_new_id(self)
super().__init__(id=id, useragent=useragent, profile=profile)
Run Code Online (Sandbox Code Playgroud)
如果您需要先等待其他列获得更新的值(因为它们可能将 Python 函数定义为 a default),那么您也可以在调用 之后运行函数super().__init__(),然后将其分配给self:
def __init__(self, useragent, profile):
"""specify the main information"""
super().__init__(useragent=useragent, profile=profile)
self.id = generate_new_id(self)
Run Code Online (Sandbox Code Playgroud)
注意:您不希望使用内置id()函数为 SQL 插入的数据生成 id,函数返回的值不保证是唯一的。它们仅对于所有活动 Python 对象的集合是唯一的,并且仅在当前进程中。下次运行 Python 时,或者当对象从内存中删除时,值可以并且将被重用,并且您无法控制它下次或完全不同的过程中生成什么值。
如果您只想创建具有useragent和profile列的唯一组合的行,那么您需要UniqueConstraint在表参数中定义 a 。不要尝试在 Python 级别检测唯一性,因为您不能保证另一个进程不会同时进行相同的检查。数据库可以更好地确定您是否有重复值,而不会冒竞争条件的风险:
class Worker(Base):
__tablename__='worker'
id = Column(Integer, primary_key=True, autoincrement=True)
profile = Column(String(100), nullable=False)
useragent = Column(String(100), nullable=False)
__table_args__ = (
UniqueConstraint("profile", "useragent"),
)
Run Code Online (Sandbox Code Playgroud)
或者您可以使用基于两列的复合主键;主键(复合或其他)必须始终是唯一的:
class Worker(Base):
__tablename__='worker'
profile = Column(String(100), primary_key=True, nullable=False)
useragent = Column(String(100), primary_key=True, nullable=False)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6580 次 |
| 最近记录: |