如何在自己的“类初始化程序”(类定义)代码中访问类__dict__
?如果不这样做,我怎样才能将类的定义属性作为字符串访问(这样可以生成名称,并以编程方式设置它们的值)
class A: # from a library by a stubborn maintainer
def __init__ (self):
self.hello = "Hello"
# + some huge misguided crap that I do not control
def f1 (self):
self.f2 ()
def f2 (self):
print self.hello
class B:
f1 = A.__dict__ ['f1'] # works
# how to loop over 2..10 and set B.f$i <- A.f$i ?
# this doesn't work:
#B.__dict__ ['f2'] = A.__dict__ ['f2'] # B not yet defined
def __init__ (self):
#self.hello = A ().hello # the actual code has to be copied manually
# misguided crap removed
a = B ()
a.f2()
最好不要复制/粘贴self.hello初始化只是为了绕过被误导的东西,但我不认为这可以很容易地帮助解决重构工具。
答案 0 :(得分:2)
抱歉,在定义课程时,你无法真正做到这一点。换句话说,您无法在自己的定义中访问类__dict__
,因为执行定义的结果将成为字典的内容(这就是为什么类名尚未绑定到任何内容)。可能最简单的解决方法是给你的班级__metaclass__
。
元类是类的类,因此它们的实例是类(因此名称)。为简单起见,我将B
中的一个定义放在其中,因为它的用法和范围仅限于该类(但是,这不能在Python 3中完成)。
__metaclass__.__new__()
中的代码仅在创建 it 的实例时执行,即在类B
的定义期间执行,而不是在类B
的实例时执行是创建的,因此复制所有方法的开销仅在发生时才会发生 - 通常是一次。请注意,因为类方法也是描述符对象,所以必须调用每个方法的__get__
方法,以便获得将它们绑定到另一个类对象的正确值。有关详细信息,请参阅文档中的Raymond Hettinger标题为Descriptor HowTo Guide的部分。
class A(object):
def __init__(self):
self.hello = "Hello"
# + some huge misguided crap that I do not control
def f1(self):
self.f2()
def f2(self):
print self.hello
class B(object):
class __metaclass__(type):
A_METHODS = ['f{}'.format(i) for i in xrange(1, 11)] # 'f1'...'f10'
def __new__(mcls, classname, bases, classdict):
classobj = type.__new__(mcls, classname, bases, classdict)
classobj.hello = A().hello
for fn in mcls.A_METHODS:
if fn in A.__dict__:
setattr(classobj, fn, A.__dict__[fn].__get__(classobj, A))
return classobj
def __init__(self):
pass
a = B()
a.f2() # --> Hello
答案 1 :(得分:1)
完全可能有更好的方法(例如分支A类并删除误导的代码,或让每个B实例保持或共享A实例,或在{{1}的定义后修改B.__dict__
完成)。
那就是说,你可以替换:
B
使用:
B.__dict__ ['f2'] = A.__dict__ ['f2'] # B not yet defined
这不保证可以正常工作,因为不允许修改locals()['f2'] = A.__dict__ ['f2']
,但它似乎至少在CPython 2.7.5中起作用:
locals()
输出class Foo:
a = locals()
locals()['b'] = 0
print Foo.a is Foo.__dict__, Foo.b
。有趣的是,如果True 0
继承自False 0
,则会输出Foo
,这表示我所处的水很难。
当然这是对特定于实现的行为的可怕滥用,不推荐,可能会出错某些地方,等等: - )