3

Many of my classes look like the following class to represent accounts

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

But really the only relevant information is the list of attributes I care about first, last, age, id, balance. Is there a standard method to define Python classes that follow this structure?

At first glance I thought of namedtuple but I'm not sure that that allows me to add additional methods after the fact. Really, I want something like the following

class Account(object):
    attributes = "first last age id balance"

    def ... # other methods

What is the best way of obtaining this?

4

3 回答 3

4

不知道它是多么地道,但以下满足您的要求:

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
于 2013-06-14T18:32:04.923 回答
1

以下是一些您可以尝试的方法:覆盖__setattr____dict____slots__/或init。让我们知道什么对您有用。

于 2013-06-14T17:38:59.517 回答
1

存在许多图书馆来满足这种需求:attrs, dataclasses, pydantic, ... 以及我对这个景观的新添加,pyfields.

选择主要取决于您需要或不需要的功能。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 表示和转换、哈希、相等和比较,您应该使用另一个库将它们添加到您的类之上。我目前正在开发一个mixture为此提供混合类的库,具有与点菜功能相同的理念 - 您可以使用或不使用pyfields.

有关详细信息,请参阅pyfields文档。不要犹豫,提供反馈!

于 2019-10-11T16:00:16.893 回答