我有一个Parent类和一个继承的子类,我想知道如何在我的Parent类中访问子类变量。
我尝试了这个但它失败了 -
class Parent(object):
def __init__(self):
print x
class Child(Parent):
x = 1;
x = Child();
错误: -
NameError: global name 'x' is not defined
这个问题与我们继承表单类的Django表单有关 并声明一些类变量。
例如: -
我的表单看起来像这样
from django import forms
class EmployeeForm(forms.Form):
fname = forms.CharField(max_length=100)
lname = forms.CharField(max_length=100)
我相信表单字段被视为类变量,并以某种方式传递给父类..
答案 0 :(得分:2)
Django用元类做到了这一点。 (Relevant Django source)
以下是相关代码的简化示例:
class Field(object):
def __init__(self, *args):
self.args = args
def __repr__(self):
return "Form(%s)" % (', '.join(map(repr, self.args)),)
class Meta(type):
def __new__(mcs, name, bases, attrs):
field_list = []
for k,v in attrs.items():
if isinstance(v, Field):
field_list.append(v)
cls = type.__new__(mcs, name, bases, attrs)
cls.fields = field_list
return cls
class Form(object):
__metaclass__ = Meta
class MyForm(Form):
fe1 = Field("Field1", "Vars1")
fe2 = Field("Field2", "Vars2")
x = "This won't appear"
form_fields = MyForm.fields
print(form_fields)
这里有很多关于Python元类(example)的问题,所以我不会试图重新解释这个概念。
在这种情况下,当您创建类MyForm
时,将检查每个类属性是否为Field
的实例。如果是,则将其添加到列表(field_list
)。
创建了类,然后将属性.fields
添加到类field_list
,即Field
元素列表。
然后,您可以通过<FormSubclass>.fields
访问表单字段,或者在此示例的情况下MyForm.fields
。
修改强>
值得注意的是,你可以完成非常相似的功能,没有元类语法糖,例如:
class Field(object):
def __init__(self, *args):
self.args = args
def __repr__(self):
return "Form(%s)" % (', '.join(map(repr, self.args)),)
class Form(object):
def __init__(self):
self._fields = None
def fields(self):
if self._fields is None:
field_list = []
for k in dir(self):
v = getattr(self, k)
if isinstance(v, Field):
field_list.append(v)
self._fields = field_list
return self._fields
class MyForm(Form):
def __init__(self):
Form.__init__(self)
self.fe1 = Field("Field1", "Vars1")
self.fe2 = Field("Field2", "Vars2")
self.x = "This won't appear"
form_fields = MyForm().fields()
print(form_fields) # [Form('Field1', 'Vars1'), Form('Field2', 'Vars2')]
答案 1 :(得分:1)
简短回答:您不从父类访问子类的属性 - 因为父类无法知道子类可能具有的属性。
长答案:...除非父类定义了一个协议,允许子类让父类知道它至少部分属性。
Django的表单框架(以及django的fmIW)使用这样的协议:基类Form
类有一个自定义元类,用于收集在{a}中声明的form.fields
子类 - 并做一些黑魔法。 FWIW,Django是oss所以你可以自己回答这个问题,只需阅读源代码:https://github.com/django/django/blob/master/django/forms/forms.py
答案 2 :(得分:-3)
您需要引用self.x
来访问Child
类变量:
class Parent(object):
def __init__(self):
print(self.x)
class Child(Parent):
x = 1
if __name__ == '__main__':
child_instance = Child()