Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
不带属性样板的Python类_Python_Oop_Metaprogramming - Fatal编程技术网

不带属性样板的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中保留信息。