为什么我可以在Python的抽象类中访问派生类的变量?
我很惊讶下面的代码运行时没有出错为什么我可以在Python的抽象类中访问派生类的变量?,python,Python,我很惊讶下面的代码运行时没有出错 # ABC class Foo(object): __metaclass__ = ABCMeta a = 1 def __init__(self, b, c): self.b = b self.c = c def get_scaled_a(self): return self.a / Bar1.a # why can I access Bar1.a? @abstrac
# ABC
class Foo(object):
__metaclass__ = ABCMeta
a = 1
def __init__(self, b, c):
self.b = b
self.c = c
def get_scaled_a(self):
return self.a / Bar1.a # why can I access Bar1.a?
@abstractmethod
def class_type(self):
pass
# Derived class 1
class Bar1(Foo):
a = 100
def class_type(self):
return 'bar1'
# Derived class 2
class Bar2(Foo):
a = 10
def class_type(self):
return 'bar2'
my_bar2_inst = Bar2(0, 0)
print(my_bar2_inst.get_scaled_a())
# 0.1
因为Python假定开发人员是成熟的人。在Python中,您通常可以访问所有属性,而不是由解释器检查您是否有权访问某个属性。这取决于你是否足够成熟,不要破坏任何东西
然而,有一种约定是,以小写字母开头的属性,如\u foo
、\u bar
和\u qux
被视为私有属性。这意味着自己访问这些文件通常不是一个好主意。但是没有任何机制可以阻止您访问它们:变量名或多或少地要求您不要访问它。如果你绝对需要它,这是你的责任
现在
Bar
的a
是Bar
类的成员,而不是Bar
实例的成员。因此,在其他一些语言中,它被认为是“静态的”。这是您可以访问它的另一个原因。当您运行get\u scaled\u a
时,Bar1
类已经定义,它的a
属性也已经定义。请记住,类也是对象,而不仅仅是类实例。因此,当定义了Bar1
时,您可以访问某些属性,而无需创建其实例
它是一个子类这一事实根本不起作用。您可以访问子类属性,原因与执行此操作相同:
>>> class myobj: pass
>>> def f(obj):
print(obj.a)
>>> obj1, obj2 = myobj(), myobj()
>>> obj1.a, obj2.a = 1, 2
>>> f(obj1)
1
>>> f(obj2)
2
类只是对象。元类只不过是类对象工厂
这是另一个例子。假设我有一个创造者:
你认为这样行吗?如果你说是的,你是对的:
>>> s = MakeMeASandwich(Reuben)
# reuben with mayo!
你为什么认为这会起作用?可能是因为函数没有理由不能访问mayo
。就在那里。它不是隐藏的。所以,它当然可以做到
再次强调:元类只不过是一个类制造工厂。它与其他工厂非常相似(尽管他们确实有一些你可能不需要的漂亮的额外的铃铛和口哨) 我没有答案,但是你的用户名很搞笑,我笑得很厉害。为什么你不能访问
Bar1.a
?这不是私事。Python甚至没有私有属性。这与a
无关,但是如果您使用的是Python 3,元类语法是class Foo(metaclass=ABCMeta):
@hiroprotation谢谢!这一变化有什么原因吗?我试图在文档中找到一些解释,但没有用。@SibbsBombling:除此之外,新语法意味着在输入类主体之前就知道元类,这样就可以存在\uuuuu prepare\uuuu
之类的东西。您是否意外地重新定义了对象
?您通常无法向确切类型为object
@user2357112的对象添加属性。我当时很轻率,很粗心。我会做得更好
>>> Reuben = type('Reuben', (), {'mayo':False}) # <-- shortcut for making a class
>>> def MakeMeASandwich(sandwich_type):
sandwich_type.mayo = True
return sandwich_type()
>>> s = MakeMeASandwich(Reuben)
# reuben with mayo!