我的课程如下:
class A:
def __init__(self):
pass
def add_attr(self, name):
setattr(self, name, 'something')
如何为self.name
定义自定义二传手,getter?我不能使用__setattr__
,__getattribute__
,因为这也会改变add_attr
的行为。
编辑:此类的用户将添加具有任意名称的任意数量的属性:
a = A()
a.add_attr('attr1')
a.add_attr('attr2')
我只希望对这些用户添加的属性进行自定义行为。
答案 0 :(得分:2)
以@Devesh Kumar Singh的答案为基础,我将以这种方式实现它:
class A:
def __init__(self):
self.attrs = {}
def __setattr__(self, key, value):
if key in self.attrs:
self.set_attr(key, value)
else:
object.__setattr__(self, key, value)
def __getattribute__(self, key):
if key in self.__dict__.get(attrs, {}):
return self.__dict__['get_attr'](self, key)
return object.__getattribute__(self, key)
def get_attr(self, key):
r = self.attrs[key]
# logic
return r
def set_attr(self, key, value):
# logic
self.attrs[key] = value
def add_attr(self, key, value=None):
self.attrs[key] = value
add_attr
仅用于首次初始化变量。您还可以编辑__setattr__
来设置self.attrs
中的所有新属性,而不是self.__dict__
答案 1 :(得分:1)
我想到的一种可能性是拥有一个动态属性字典,并使用该字典设置和获取动态属性
class A:
def __init__(self):
#Dictionary of attributes
self.attrs = {}
#Set attribute
def set_attr(self, name):
self.attrs[name] = 'something'
#Get attribute
def get_attr(self, name):
return self.attrs.get(name)
a = A()
a.set_attr('var')
print(a.get_attr('var'))
输出将为something
或者替代方法是使用property
装饰器在类外部显式添加参数,如here
class A:
def __init__(self):
pass
a = A()
#Add attributes via property decorator
a.attr_1 = property(lambda self: self.attr_1)
a.attr_2 = property(lambda self: self.attr_2)
#Assign them values and print them
a.attr_1 = 4
a.attr_2 = 6
print(a.attr_1, a.attr_2)
输出将为4 6
答案 2 :(得分:1)
自定义getter和setter逻辑?这就是property
的用途。通常,这些用于魔术屏蔽函数调用,并使它们看起来像属性访问
class MyDoubler(object):
def __init__(self, x):
self._x = x
@property
def x(self):
return x * 2
@x.setter
def x(self, value):
self._x = value
>>> md = MyDoubler(10)
>>> md.x
20
>>> md.x = 20
>>> md.x
40
>>> md._x
20
但是没有规则说您不能滥用该功能为自定义器和自定义器添加自定义行为。
class A(object):
def __init__(self):
pass
@staticmethod
def default_getter_factory(name):
def default_getter(self):
return self.name
return default_getter
@staticmethod
def default_setter_factory(name):
def default_setter(self, value):
setattr(self, name, value)
return default_setter
def add_attr(self, name, getterfactory=None, setterfactory=None):
private_name = f"_{name}"
if getterfactory is None:
getterfactory = self.__class__.default_getter_factory
if setterfactory is None:
setterfactory = self.__class__.default_setter_factory
getter, setter = getterfactory(private_name), setterfactory(private_name)
getter = property(getter)
setattr(self.__class__, name, getter)
setattr(self.__class__, name, getter.setter(setter))
这说起来有点愚蠢,而且很可能您试图做的事情都是不应该做的。动态编程是件好事,但是如果我要回顾做到这一点的代码,那么在批准其他解决方案之前,我会思考很长时间并且很难。这对我来说有点技术债务。
答案 3 :(得分:1)
我将回答自己的问题,仅供参考。这是基于此处其他人的答案。想法是对未通过__setattr__
添加的属性使用默认的__getattribute__
和add_attr
。
class A:
def __init__(self):
self.attrs = {}
def add_attr(self, name):
self.attrs[name] = 'something'
def __getattribute__(self, name):
try:
object.__getattribute__(self, 'attrs')[name] # valid only if added by user
# custom logic and return
except (KeyError, AttributeError):
return object.__getattribute__(self, name)
def __setattr__(self, name, val):
# similar to __getattribute__