在Python中,如何在类语句中获取对当前类对象的引用?例如:
def setup_class_members(cls, prefix): setattr(cls, prefix+"_var1", "hello") setattr(cls, prefix+"_var2", "goodbye") class myclass(object): setup_class_members(cls, "coffee") # How to get "cls"? def mytest(self): print(self.coffee_var1) print(self.coffee_var2) x = myclass() x.mytest() >>> hello >>> goodbye
我已经注销的替代方案是:
使用locals()
:这会在可以写入的类语句中提供一个dict。这似乎适用于类,但文档告诉您不要这样做。 (如果有人可以向我保证这种情况会持续一段时间,我可能会选择这种替代方案。)
在class
语句之后向类对象添加成员:我的实际应用程序是使用动态创建的QWidget
类属性派生PyQt4 pyqtProperty
类。 QWidget
很不寻常,因为它有一个自定义元类。非常粗略地,元类编译pyqtProperties
列表并将其存储为附加成员。因此,创建后添加到类中的属性不起作用。举例来说明这一点:
from PyQt4 import QtCore, QtGui # works class MyWidget1(QtGui.QWidget): myproperty = QtCore.pyqtProperty(int) # doesn't work because QWidget's metaclass doesn't get to "compile" myproperty class MyWidget2(QtGui.QWidget): pass MyWidget2.myproperty = QtCore.pyqtProperty(int)
请注意,上述内容适用于大多数编程案例;我的情况恰好是那些不寻常的角落案例之一。
答案 0 :(得分:3)
AFAIK有两种方法可以做你想做的事:
使用metaclass,这将在类创建时创建两个变量(我认为这就是你想要的):
class Meta(type):
def __new__(mcs, name, bases, attr):
prefix = attr.get("prefix")
if prefix:
attr[prefix+"_var1"] = "hello"
attr[prefix+"_var2"] = "goodbye"
return type.__new__(mcs, name, bases, attr)
class myclass(object):
__metaclass__ = Meta
prefix = "coffee"
def mytest(self):
print(self.coffee_var1)
print(self.coffee_var2)
在实例化时创建两个类变量:
class myclass(object): prefix =“coffee”
def __init__(self):
setattr(self.__class__, self.prefix+"_var1", "hello")
setattr(self.__class__, self.prefix+"_var2", "goodbye")
def mytest(self):
print(self.coffee_var1)
print(self.coffee_var2)
N.B:我不确定你想要实现什么,因为如果你想根据prefix
变量创建动态变量,你为什么要像在mytest
方法中一样进行访问?我希望这只是一个例子。
答案 1 :(得分:3)
对于Python 3,该类必须声明为
class myclass(object, metaclass = Meta):
prefix = "coffee"
...
其他几点:
元类可以是可调用的,而不仅仅是一个类(Python 2& 3)
如果您班级的基类已经有非标准元类,则必须确保将其称为__init__()
和__new__()
方法而不是类型。
class语句接受传递给元类的关键字参数(仅限Python 3)
使用以上所有内容在Python 3中重写mouad的解决方案是......
def MetaFun(name, bases, attr, prefix=None):
if prefix:
attr[prefix+"_var1"] = "hello"
attr[prefix+"_var2"] = "goodbye"
return object.__class__(name, bases, attr)
class myclass(object, metaclass = MetaFun, prefix="coffee"):
def mytest(self):
print(self.coffee_var1)
print(self.coffee_var2)
答案 2 :(得分:2)
您可以使用另外两种方法:
一个类装饰器。
def setup_class_members(prefix):
def decorator(cls):
setattr(cls, prefix+"_var1", "hello")
setattr(cls, prefix+"_var2", "goodbye")
return cls
return decorator
@setup_class_members("coffee")
class myclass(object):
# ... etc
特别是如果你需要以各种组合添加属性,装饰器方法很好,因为它对继承没有任何影响。
如果您要处理一组希望以各种方式组合的一小部分属性,则可以使用mixin类。 mixin类是一个常规类,它只是为了将各种属性“混合”到其他类中。
class coffee_mixin(object):
coffee_var1 = "hello"
coffee_var2 = "goodbye"
class tea_mixin(object):
tea_var1 = "good morning old bean"
tea_var2 = "pip pip cheerio"
class myclass(coffee_mixin, tea_mixin):
# ... etc
答案 3 :(得分:1)
请参阅zope.interface.declarations._implements
以获取此类魔法的示例。请注意,这是一个严重的可维护性和可移植性风险。