将属性添加到 python class
Add attribute to python class
考虑以下代码:
class Foo():
pass
Foo.entries = dict()
a = Foo()
a.entries['1'] = 1
b = Foo()
b.entries['3'] = 3
print(a.entries)
这将打印:
{'1': 1, '3': 3}
因为条目是作为静态属性添加的。有没有办法猴子修补 class 定义以添加新属性(不使用继承)。
我设法找到了以下方法,但对我来说它看起来很复杂:
def patch_me(target, field, value):
def func(self):
if not hasattr(self, '__' + field):
setattr(self, '__' + field, value())
return getattr(self, '__' + field)
setattr(target, field, property(func))
patch_me(Foo, 'entries', dict)
通常,属性是通过 __init__()
函数或实例化后添加的:
foo = Foo()
foo.bar = 'something' # note case
如果您想自动执行此操作,继承是迄今为止最简单的方法:
class Baz(Foo):
def __init__(self):
super().__init__() # super() needs arguments in 2.x
self.bar = 'something'
请注意,classes 不需要出现在 Python 模块的顶层。您可以在函数内声明一个 class:
def make_baz(value):
class Baz(Foo):
def __init__(self):
super().__init__() # super() needs arguments in 2.x
self.bar = value()
return Baz()
此示例将在每次调用 make_baz()
时创建一个新的 class。这可能是也可能不是你想要的。这样做可能会更简单:
def make_foo(value):
result = Foo()
result.bar = value()
return result
如果您真的打算对 原始 class 进行猴子修补,您提供的示例代码或多或少是最简单的方法。您可能会考虑对 property()
使用装饰器语法,但这是一个小改动。我还应该注意,它 不会 调用双下划线名称重整,这可能是一件好事,因为这意味着您不能与 class 本身使用的任何名称冲突。
考虑以下代码:
class Foo():
pass
Foo.entries = dict()
a = Foo()
a.entries['1'] = 1
b = Foo()
b.entries['3'] = 3
print(a.entries)
这将打印:
{'1': 1, '3': 3}
因为条目是作为静态属性添加的。有没有办法猴子修补 class 定义以添加新属性(不使用继承)。
我设法找到了以下方法,但对我来说它看起来很复杂:
def patch_me(target, field, value):
def func(self):
if not hasattr(self, '__' + field):
setattr(self, '__' + field, value())
return getattr(self, '__' + field)
setattr(target, field, property(func))
patch_me(Foo, 'entries', dict)
通常,属性是通过 __init__()
函数或实例化后添加的:
foo = Foo()
foo.bar = 'something' # note case
如果您想自动执行此操作,继承是迄今为止最简单的方法:
class Baz(Foo):
def __init__(self):
super().__init__() # super() needs arguments in 2.x
self.bar = 'something'
请注意,classes 不需要出现在 Python 模块的顶层。您可以在函数内声明一个 class:
def make_baz(value):
class Baz(Foo):
def __init__(self):
super().__init__() # super() needs arguments in 2.x
self.bar = value()
return Baz()
此示例将在每次调用 make_baz()
时创建一个新的 class。这可能是也可能不是你想要的。这样做可能会更简单:
def make_foo(value):
result = Foo()
result.bar = value()
return result
如果您真的打算对 原始 class 进行猴子修补,您提供的示例代码或多或少是最简单的方法。您可能会考虑对 property()
使用装饰器语法,但这是一个小改动。我还应该注意,它 不会 调用双下划线名称重整,这可能是一件好事,因为这意味着您不能与 class 本身使用的任何名称冲突。