不带属性样板的Python类
我的许多类看起来像下面的类来表示帐户不带属性样板的Python类,python,oop,metaprogramming,Python,Oop,Metaprogramming,我的许多类看起来像下面的类来表示帐户 class Account(object): def __init__(self, first, last, age, id, balance): self.first = first self.last = last self.age = age self.id = id self.balance = balance def _info(self):
class Account(object):
def __init__(self, first, last, age, id, balance):
self.first = first
self.last = last
self.age = age
self.id = id
self.balance = balance
def _info(self):
return self.first, self.last, self.age, self.id, self.balance
def __eq__(self, other):
return self._info == other._info()
def __hash__(self):
return hash((type(self), self.info()))
def ... # other methods follow
但实际上,唯一相关的信息是我关心的属性列表第一、最后、年龄、id、余额。是否有标准方法来定义遵循此结构的Python类
乍一看,我想到了namedtuple
,但我不确定这是否允许我在事后添加其他方法。真的,我想要下面这样的东西
class Account(object):
attributes = "first last age id balance"
def ... # other methods
获取此信息的最佳方式是什么?:覆盖\uuuuuuuuuuuuuuuuuuuuuuuu设置属性、\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
、和/或初始化。让我们知道什么适合您。不确定它的惯用性,但以下内容满足您的要求:
class Slottable:
def __init__(self, *args):
for slot, arg in zip(self.slots.split(' '), args):
setattr(self, slot, arg)
def _info(self):
return tuple(getattr(self, attr) for attr in self.slots.split())
def __eq__(self, other):
return self._info() == other._info()
def __hash__(self):
return hash((type(self), self._info()))
class Account(Slottable):
slots = "first last age id balance"
def fullname(self):
return self.first + " " + self.last
matt = Account("Matthew", "Smith", 28, 666, 1E6)
john = Account("John", "Jones", 46, 667, 1E7)
d = {matt: 5, john: 6} # Hashable
print matt.fullname()
#=> "Matthew Smith"
print john.fullname()
#=> "John Jones"
print matt == matt, matt == john
#=> True False
matt.age = 29 # Happy birthday!
print matt.age
#=> 29
有许多库可以满足这一需求:attrs
,dataclasses
,pydantic
。。。还有我在这片土地上的新成员
选择将主要取决于您需要或不需要的功能pyfields
关注字段定义和可选的验证和转换,对类没有任何约束。可以是本机的字段的速度与python本机属性的速度一样快,而需要回调(验证器/转换器)的字段是使用描述符实现的
您可以将自己的构造函数与
from pyfields import field, init_fields
class Account(object):
first = field(doc="first name")
last = field(doc="last name")
age = field(doc="the age in years")
id = field(doc="an identifier")
balance = field(doc="current balance in euros")
@init_fields
def __init__(self, msg):
print(msg)
a = Account("hello, world!", first="s", last="marie", age=135, id=0, balance=-200000)
print(vars(a))
屈服
hello, world!
{'balance': -200000, 'id': 0, 'age': 135, 'last': 'marie', 'first': 's'}
与其他更多的“一体式”库不同,pyfields
以“最小可行产品”的精神只关注字段和构造函数。因此,如果您还想要dict表示和转换、散列、相等和比较,您应该使用另一个库将它们添加到类的顶部。我目前正在开发一个lib,它提供了这方面的混合类,具有与点菜功能相同的理念——您可以使用或不使用pyfields
有关详细信息,请参阅。不要犹豫,提供反馈 Hrm,这不能很好地处理突变。特别是它没有遵循单点真理原则。冗余数据保存在\u info
和每个属性中。@MRocklin?你为什么想要那个?!?:-)我编辑了这个例子来处理变异,并且只在attributes dict中保留信息。