我正在编写一个python(3.2+)插件库,我想创建一个函数,它将创建一些从配置文件自动处理的变量。
用例如下(类变量):
class X:
option(y=0)
def __init__(self):
pass
(实例变量):
class Y:
def __init__(self):
option(y=0)
选项草案代码如下:
def option(**kwargs):
frame = inspect.stack()[1][0]
locals_ = frame.f_locals
if locals_ == frame.f_globals:
raise SyntaxError('option() can only be used in a class definition')
if '__module__' in locals_:
# TODO
else:
for name, value in kwargs.items():
if not name in locals_["self"].__class__.__dict__:
setattr(locals_["self"].__class__, name, VirtualOption('_'+name, static=False))
setattr(locals_["self"], '_'+name,value)
第一种情况我有问题,当选项被声明为类变量时。是否有可能以某种方式引用使用此函数的类(例如在类X中)?
答案 0 :(得分:2)
您无法获取对该类的引用,因为尚未创建该类。您的父框架指向一个临时函数,其完成后的locals()
将用作类体。
因此,您需要做的就是将变量添加到父框架本地,并在类构造完成时将这些变量添加到类中。
简短演示:
>>> def foo():
... import sys
... flocals = sys._getframe(1).f_locals
... flocals['ham'] = 'eggs'
...
>>> class Bar:
... foo()
...
>>> dir(Bar)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__locals__', '__lt__', '__module__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'ham']
>>> Bar.ham
'eggs'
答案 1 :(得分:0)
在我看来,元类在这里是合适的:
python2.x语法
def class_maker(name,bases,dict_):
dict_['y']=0
return type(name,bases,dict_)
class X(object):
__metaclass__ = class_maker
def __init__(self):
pass
print X.y
foo = X()
print foo.y
python3.x语法
似乎python3在类定义中使用metaclass
关键字:
def class_maker(name,bases,dict_):
dict_['y']=0
return type(name,bases,dict_)
class X(metaclass=class_maker):
def __init__(self):
pass
print( X.y )
foo = X()
print( foo.y )
print( type(foo) )
或者,更像你在问题中的内容:
def class_maker(name,bases,dict_,**kwargs):
dict_.update(kwargs)
return type(name,bases,dict_)
class X(metaclass=lambda *args: class_maker(*args,y=0)):
def __init__(self):
pass
print( X.y )
foo = X()
print( foo.y )
print( type(foo) )