使用类实例作为类属性,描述符和属性

Chr*_*ris 8 python properties class descriptor new-style-class

我最近曾说过尝试在Python中使用更新的类(从对象派生的类).作为熟悉它们的例外,我试图定义一个类,它有许多类实例作为属性,每个类实例描述不同类型的数据,例如1d列表,2d数组,标量等.基本上我希望能够写作

some_class.data_type.some_variable
Run Code Online (Sandbox Code Playgroud)

where data_type是一个描述变量集合的类实例.下面是我第一次尝试实现它,只使用一个profiles_1d实例而非通用名称:

class profiles_1d(object):
    def __init__(self, x, y1=None, y2=None, y3=None):
        self.x = x
        self.y1 = y1
        self.y2 = y2
        self.y3 = y3

class collection(object):
    def __init__(self):
        self._profiles_1d = None

    def get_profiles(self):
        return self._profiles_1d

    def set_profiles(self, x, *args, **kwargs):
        self._profiles_1d = profiles_1d(x, *args, **kwargs)

    def del_profiles(self):
        self._profiles_1d = None

    profiles1d = property(fget=get_profiles, fset=set_profiles, fdel=del_profiles,
        doc="One dimensional profiles")
Run Code Online (Sandbox Code Playgroud)

以上代码大致是解决此问题的适当方法.我看到的使用的例子property只是设置了一些变量的值.在这里,我需要使用set方法初始化某个类的实例.如果没有,将非常感谢任何其他更好的方法来实现这一点的建议.

另外,我定义set方法的方式是否正确?通常,根据我的理解,set方法定义了用户键入时要执行的操作,在此示例中,

collection.profiles1d = ...
Run Code Online (Sandbox Code Playgroud)

我可以profiles_1d使用上面的代码正确设置实例属性的唯一方法是键入collection.set_profiles([...], y1=[...], ...),但我认为我不应该直接调用此方法.理想情况下我想输入collection.profiles = ([...], y1=[...], ...):这是正确/可能的吗?

最后,我看到一个装饰器提到了很多类型的新风格,但这是我所知道的很少.在这里使用装饰器是否合适?对于这个问题,这是我应该知道的吗?

agf*_*agf 10

首先,你正在学习新式课程.他们有很多优点.

在Python中创建属性的现代方法是:

class Collection(object):
    def __init__(self):
        self._profiles_1d = None

    @property
    def profiles(self):
        """One dimensional profiles"""
        return self._profiles_1d

    @profiles.setter
    def profiles(self, argtuple):
        args, kwargs = argtuple
        self._profiles_1d = profiles_1d(*args, **kwargs)

    @profiles.deleter
    def profiles(self):
        self._profiles_1d = None
Run Code Online (Sandbox Code Playgroud)

然后profiles通过做

collection = Collection()
collection.profiles = (arg1, arg2, arg3), {'kwarg1':val1, 'kwarg2':val2}
Run Code Online (Sandbox Code Playgroud)

注意所有三个具有相同名称的方法.

通常不会这样做; 要么让它们将属性传递给collections构造函数,要么让它们创建profiles_1d自己,然后collections.profiles = myprofiles1d将它或传递给构造函数.

如果希望属性管理对自身的访问而不是管理对属性的访问的类,请将该属性设为具有描述符的类.如果与上面的属性示例不同,您实际上需要存储在属性中的数据(而不是另一个,faux-private实例变量),请执行此操作.此外,如果您要反复使用相同的属性,那么它很有用 - 使它成为描述符,您不需要多次编写代码或使用基类.

我实际上喜欢@ S.Lott的页面 - Python的属性,属性和描述符中的构建技巧.