Python 属性创建者函数

Python 属性创建者函数,python,properties,Python,Properties,我希望在一个对象中有一个函数,用于创建某个行为的成员。与使用@property装饰器类似。但是不必声明getter和setter函数。我想用相同的getter和setter函数创建自定义行为的许多成员。然而,这个例子不起作用。当我运行它时,new_prop成员是一个属性对象,而不是一个成员。我怎样才能实现我的目标 class MyClass(): def __init__(self): self.new_prop("my_prop1") self.new_

我希望在一个对象中有一个函数,用于创建某个行为的成员。与使用@property装饰器类似。但是不必声明getter和setter函数。我想用相同的getter和setter函数创建自定义行为的许多成员。然而,这个例子不起作用。当我运行它时,
new_prop
成员是一个属性对象,而不是一个成员。我怎样才能实现我的目标

class MyClass():
    def __init__(self):
        self.new_prop("my_prop1")
        self.new_prop("my_prop2")
        self.new_prop("my_prop3")

    def new_prop(self, name):
        def getter(self):
            this_prop = getattr(self, "_" + name)
            if this_prop is None:
                return "This is None!"
            else:
                return this_prop
        def setter(self, value):
            setattr(self, "_" + name, value)
        setattr(self, name, property(getter, setter))
        setattr(self, "_" + name, None)

if __name__ == "__main__":
    my_class = MyClass()

    print(type(my_class.my_prop1))

请注意,属性被声明为类属性。因此,您必须在类而不是实例上设置它:

setattr(self.__class__, name, property(getter, setter))
这是否有用是另一个问题,特别是为每个实例在
\uuuu init\uuuu
中设置class属性。你应该考虑在类之外实现你自己的描述符,这样你就可以做到:

class MyClass():
     my_prop1 = new_prop("my_prop1")
     my_prop2 = new_prop("my_prop2")
     my_prop3 = new_prop("my_prop3")

请注意,属性被声明为类属性。因此,您必须在类而不是实例上设置它:

setattr(self.__class__, name, property(getter, setter))
这是否有用是另一个问题,特别是为每个实例在
\uuuu init\uuuu
中设置class属性。你应该考虑在类之外实现你自己的描述符,这样你就可以做到:

class MyClass():
     my_prop1 = new_prop("my_prop1")
     my_prop2 = new_prop("my_prop2")
     my_prop3 = new_prop("my_prop3")

property
是一个描述符,与所有描述符一样,它只有在作为类属性解析时才被调用-正如您所发现的,当它是实例属性时,它是
\uuuuuuuuu get\uuuuuu
\uuuu set\uuuuuuu
方法不会被调用

如果您的目的只是为了避免为N个属性重写相同的getter和setter,那么简单的解决方案就是编写您自己的描述符:

class MyProp(object):
    def __init__(self, name):
        self.name = name

    def __get__(self, obj, cls):
        if obj is None:
            return self
        value = getattr(obj, "_" + self.name)
        if value is None:
           return "This is None!"
        else:
           return value

    def __set__(self, obj, value):
        setattr(obj, "_" + self.name, value)


class Foo(object):
    prop1 = MyProp("prop1")
    prop2 = MyProp("prop2")

property
是一个描述符,与所有描述符一样,它只有在作为类属性解析时才被调用-正如您所发现的,当它是实例属性时,它是
\uuuuuuuuu get\uuuuuu
\uuuu set\uuuuuuu
方法不会被调用

如果您的目的只是为了避免为N个属性重写相同的getter和setter,那么简单的解决方案就是编写您自己的描述符:

class MyProp(object):
    def __init__(self, name):
        self.name = name

    def __get__(self, obj, cls):
        if obj is None:
            return self
        value = getattr(obj, "_" + self.name)
        if value is None:
           return "This is None!"
        else:
           return value

    def __set__(self, obj, value):
        setattr(obj, "_" + self.name, value)


class Foo(object):
    prop1 = MyProp("prop1")
    prop2 = MyProp("prop2")

有没有什么方法可以不用写‘prop1=MyProp(“prop1”)’,而是像‘add_prop(“prop1”)’这样使用您的解决方案呢?没有,或者至少没有一些非常讨厌的黑客,即使这样。。。这与
语句的工作方式以及类对象的构建方式有关-基本上,
语句在
块的顶层执行所有语句,在dict中收集在该块中创建的所有名称,将该dict传递给
类型(),并将结果类对象绑定到封闭命名空间中的类名。这意味着在执行
prop1=MyProp(…)
语句时,该类还不存在,因此
MyProp
无法访问它。为什么当obj=None时该类会返回self?@Benjamin由于该描述符依赖实例进行数据存储,因此在查找该类时无法返回任何有意义的值。在这种情况下,返回自我是典型的行为,参见内置的
属性
类型。是否有任何方法可以使用您的解决方案,而不必编写“prop1=MyProp(“prop1”)”,而是类似于:“add_prop(“prop1”)”这样的内容?不,或者至少不需要一些非常讨厌的黑客,即使如此。。。这与
语句的工作方式以及类对象的构建方式有关-基本上,
语句在
块的顶层执行所有语句,在dict中收集在该块中创建的所有名称,将该dict传递给
类型(),并将结果类对象绑定到封闭命名空间中的类名。这意味着在执行
prop1=MyProp(…)
语句时,该类还不存在,因此
MyProp
无法访问它。为什么当obj=None时该类会返回self?@Benjamin由于该描述符依赖实例进行数据存储,因此在查找该类时无法返回任何有意义的值。在这种情况下,返回self是标准行为,参见内置的
属性
类型。