我想实现一些像这样工作的东西:
memo = Note("memo",5)
report = Note("report",20)
notebook = Notebook(memo,report)
print str(notebook.memo) # 5 expected
print str(notebook.report) # 20 expected
灵感来自:http: //znasibov.info/blog/html/2010/03/10/python-classes-dynamic-properties.html 和 How to implement property() with dynamic name (in python) ,我实现了以下代码:
class Note:
def __init__(self,name,size):
self.name = name
self.size = size
class Notebook(object):
def __new__(cls,*notes):
notebook = object.__new__(cls)
setattr(notebook,'_notes',{note.name : note.size for note in notes})
functions = [lambda notebook : notebook._notes[note.name] for note in notes]
for note,function in zip(notes,functions) :
#version 1
setattr(notebook.__class__, note.name, property(function))
#version 2 -- note : __class__ removed
#setattr(notebook, note.name, property(function))
return notebook
注意:我知道对于这个最小的代码使用__new__
代替__init__
是不合理的,但是稍后当我使用的子类时需要这样做Notebook
如果我使用版本 1: 1. 而不是拥有5
和20
被打印,它会打印20
和20
. 我不明白为什么。打印函数会显示具有不同地址的函数数组。2. 我使用__class__
了上面给出的博客条目的启发,但我不确定它的作用。它使属性成为类属性?(在我的情况下这将是非常糟糕的)
如果我使用版本 2:打印类似property object at 0x7fb86a9d9b50
. 这似乎是有道理的,但我不确定我是否理解为什么它不会为版本 1 打印相同的内容。
有没有办法解决这个问题,使用任一版本(或另一种完全不同的方法)?
编辑
提出了解决该问题的有趣答案。这里对应的代码:
class Note:
def __init__(self,name,value):
self.name = name
self.size = value
def _get_size(self,notebook_class=None): return self.size+1
class Notebook(object):
def __new__(cls,*notes):
notebook = object.__new__(cls)
notebook._notes = {note.name : note.size for note in notes}
for note in notes : setattr(notebook.__class__, note.name, property(note._get_size))
return notebook
问题是:现在这个测试代码没有给出想要的输出:
memo1 = Note("memo",5)
report1 = Note("report",20)
notebook1 = Notebook(memo1,report1)
print str(notebook1.memo) # print 6 as expected (function of Note return size+1)
print str(notebook1.report) # print 21 as expected
memo2 = Note("memo",35)
report2 = Note("report",40)
notebook2 = Notebook(memo2,report2)
print str(notebook2.memo) # print 36 as expected
print str(notebook2.report) # print 41 expected
print str(notebook1.memo) # does not print 6 but 36 !
print str(notebook1.report) # does not print 21 but 41 !
我想这是可以预料的,因为该属性已添加到课程中……无论如何要克服这个问题?