Python:父类实例的子实例类

2024-06-08 06:51:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我是新来的

我想知道何时初始化父类实例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__

问题2:现在如果我创建一个实例z = B(),我想创建z作为P的一个子实例,即z应该只在前面的实例P存在的情况下创建。 并且P的属性应该向下流到zw/如果有添加到属性中的数据。 基本上,如果不存在P,就不应该创建z

类似地y = B() iff x = A() 有办法吗?

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

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

有自检程序来检查吗?我是说怎么做到的?

在第2季度更新:另一种方法是,在创建实例以检查某个类的实例并获取特定实例数据时,是否有方法签入B类? 就像在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?

Tags: 数据实例nameself程序属性objectinit
3条回答
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

I want to create z as a sub-instance of P i.e. z should only be created if an earlier instance P exists. And the attributes of P should flow down to z w/ the data if any added to attributes.

1)为什么称z为p的“子实例”?你说使z成为一个“子实例”等同于仅当P的实例存在时创建z。怎么会这样?这种“子实例”语言从何而来?如果20已经存在,您是否还说整数10是20的“子实例”?

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

更新2)

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

您没有在B中调用__init__。使用函数名只会得到该函数对象。__init__()后面的括号实际上执行了该函数。

super(B, self)返回一个类,而不是一个对象(这是有意义的——一个类没有superinstance,它有一个超类),因此您随后对该类调用__class__,这将导致意外的结果。在self上使用__class__,因为self是类的实例。

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

注意我在访问type()时使用__class__-使用内置函数比直接访问magic值要好。它可读性更强,并允许特殊功能。

根据阅读你更新的第二季度,再看看你的第一季度,听起来你对课程和他们能为你做什么有一个基本的误解。(这是有道理的,因为你说你“不熟悉OOP”。)

我将在这里讨论术语,除非我知道您熟悉哪些非eem>-OOP语言,但我将使用一个C示例并故意掩盖一系列问题,并声明您的class A就像一个struct A,而您的class B只是一个struct B,它包含了整个^{}:

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

如果您创建了一个新的B实例,则无法更改其a成员的类型,它将始终是一个实际的A。不管是否有一个struct A2(类型实例),一个B的内容只包含一个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!'

(在C语言中,至少有一个指针,如果它是void *-意味着你可以指向你需要的任何类型,或者根本不指向任何类型,就像上面的B可以连接到None而不是一些A1或A2,或者只要它有.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!
>>> 

当然,你可以让B__init__自己找到一个A1或A2(如果存在的话),如果显式传递它不是你想要的。

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


编辑到地址Q3:在解释器中,您可以看到为什么打印super(B, self).__class__.__name__只打印“super”。完成了z = B()

>>> type(z)
<class '__main__.B'>
>>> super(B, z)
<super: <class 'B'>, <B object>>

调用super只会得到这个特殊的proxy object。代理对象是实例如何调用“向上”(技术上称为“mro”-wards);遵循Python2文档中的链接。

相关问题 更多 >

    热门问题