Python:父类实例的子实例类

时间:2013-06-13 17:50:25

标签: python class oop python-2.7

我是OOPS的新手

我想知道何时初始化父类实例P并且我想初始化子类实例C

喜欢

class A(object):
    def __init__(self):
        print "A created"
P = A()


class B(A):
    def __init__(self):
        print super((B), self).__init__ # Q1: How to get "A created" from parent class?
        print self.__class__.__name__
        print super(B, self).__class__.__name__

Q2:现在,如果我创建一个实例z = B(),我想创建z作为P的子实例,即只有早期才会创建z实例P存在。 如果添加到属性中,P的属性应该向下流到z w / data。 基本上,如果z不存在,则不应创建P

同样y = B() iff x = A() 有没有办法做到这一点?

我这样做是因为我正在创建一个程序,其中将在各种上下文中创建类A的多个实例,例如

Mathematics = A()
English = A()
Now,
Algebra = B() iff Mathematics = A()
And 
Grammar = B() iff English = A()

是否有自检者检查?我的意思是怎么做的?

Q2更新: 另一种问题是,有没有办法在创建实例时检查B类,以检查A类的实例并获取特定实例数据? 就像在B类中检查由A类组成的实例然后选择一个并从该实例的属性获取数据到创建B类的实例

另外

 z = B()
    <bound method B.__init__ of <__main__.B object at 0x000000000791DB38>>
    B
super #Q3: I thought it would print `A`. WHY NOT?

3 个答案:

答案 0 :(得分:3)

您未在__init__中致电B。使用函数的名称只是为您提供该函数对象。 __init__()实际执行函数后的括号。

super(B, self)返回一个类,而不是一个对象(这是有意义的 - 一个类没有超级实例,它有一个超类),所以你然后在该类上调用__class__,结果在意想不到的结果。您在__class__上使用self,因为self是该类的实例。

class B(A):
    def __init__(self):
        super(B, self).__init__()
        print type(self).__name__
        print super(B, self).__name__

请注意,我使用type()而不是访问__class__ - 使用内置函数比直接访问魔术值更好。它更具可读性,并允许特殊功能。

答案 1 :(得分:1)

class A(object):
    def __init__(self):
        print "A created"

class B(A):
    def __init__(self):
        super(B, self).__init__() # Q1: How to get "A created" from parent class?

b = B()


--output:--
A created
  

我想创建z作为P的子实例,即z应该只是   如果存在早期实例P,则创建。和P的属性   应该向下流到z w /数据(如果有的话添加到属性中)。

1)你为什么称z为P的'子实例'?你说,只有当P的实例存在时,使z成为'子实例'与创建z是等价的(“即”)。怎么会这样?这个“子实例”语言来自哪里?你是否也说整数10是20的“子实例”,如果20已存在?

2)P不是一个类,因此P的任何属性都不会流到任何地方。

UPDATE2)

class A(object):
    def __init__(self, name):
        self.name = name

class B(A):
    def __init__(self, anA, age):
        super(B, self).__init__(anA.name)
        self.age = age



existingA = {}
a = A("Sally")
existingA["Sally"] = a
a = A("George")
existingA["George"] = a


x = "Sally"
if x in existingA:
    b = B(existingA[x], 30) 
    print b.name, b.age


--output:--
Sally 30

答案 2 :(得分:0)

基于阅读更新的Q2并再次查看Q1,听起来您对课程有一个基本的误解,以及他们可以为您做些什么。 (这是有道理的,因为你说你是“OOP新手”。)

除非我知道您熟悉哪种 -OOP语言,否则我将在这里违反术语,但我将使用C示例并故意掩盖一大堆问题,并声称您的class Astruct A类似,而您的class B只是struct B 包含整个struct A

struct A {
    int x, y; /* ... etc */
};
struct B {
    struct A a;
    int z;
}

如果您创建B的新实例,则无法使其a成员的类型更改,它始终是实际的{{ 1}}。如果有A(类型实例),则无关紧要,struct A2的内容只包含一个B

听起来你想要的根本不是子类,而只是一个普通的成员,(在C中)更像是有一些指针其他对象,而不是用身体结合它:

A

(在C中,至少有一个指针,如果它是class A1(object): def __init__(self): pass def about(self): print 'I am an A1' class A2(object): def __init__(self): pass def about(self): print 'I am an A2' class B(object): def __init__(self, connected_to = None): self.connected_to = connected_to def about(self): print 'I am a B' if self.connected_to is not None: print '... and I am connected to a %s:' % type(self.connected_to) self.connected_to.about() # and ask it to describe itself else: print '... and I am connected to no one!' - 意味着您可以指向您需要的任何类型,或者根本不指向任何类型,就像上面的void *一样connected_to B而不是某些A1或A2,或者实际上只要有None的任何东西。)

鉴于上述情况,您可以这样做:

.about()

当然,你可以让>>> B(A1()).about() I am a B ... and I am connected to a <class '__main__.A1'>: I am an A1 >>> B(A2()).about() I am a B ... and I am connected to a <class '__main__.A2'>: I am an A2 >>> B().about() I am a B ... and I am connected to no one! >>> 的{​​{1}}自己找到A1或A2(如果存在),如果明确地传递它不是你想要的。

当然,这会模糊为您做的(子)类。根据上面的示例,您可以创建一个类B,然后创建一个子类__init__,也可以创建另一个子类Maths(object)。另外,您可以创建一个类Algebra(Maths)和一个子类Topology(Maths),以及另一个子类HumanLanguage(object)。但是你不会创建一个子类English(HumanLanguage),而Russian(HumanLanguage)可能有意义。


编辑以解决问题3:在解释器中,您可以看到为什么打印Ring(HumanLanguage)仅打印“超级”。完成Ring(Algebra)

super(B, self).__class__.__name__

调用z = B()只会让您获得此特殊proxy object。代理对象是实例可以如何调用“向上”(技术上,“mro”向下);按照Python2文档中的链接。