1

我是 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(),我想创建一个iez的子实例,只有在存在较早的实例时才应该创建。如果添加到属性中,则属性应该向下流向w/ 数据。如果不存在,基本上不应该创建PzPPzzP

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

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

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

有自检器来检查吗?我的意思是这是怎么做到的?

Q2 更新: 另一种询问方式是,是否有办法在创建实例以检查 A 类的实例并获取特定实例数据的同时检查 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?
4

3 回答 3

3

你没有打电话__init__进来B。使用函数的名称只是为您提供该函数对象。__init__()实际执行函数后的括号。

super(B, self)返回一个类,而不是一个对象(这是有道理的 - 一个类没有超实例,它有一个超类),因此您然后调用__class__该类,这会导致意外结果。您使用__class__onself因为self是该类的一个实例。

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

请注意我对type()过度访问的使用__class__- 使用内置函数比直接访问魔法值更好。它更具可读性并允许特殊功能。

于 2013-06-13T17:54:42.957 回答
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 的属性应该向下流向 zw/ 数据。

1)你为什么称 za 为 P 的“子实例”?您说仅当存在 P 的实例时才使 za '子实例'等效于(“ie”)创建 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
于 2013-06-13T18:10:34.233 回答
0

Based on reading your updated Q2 and looking at your Q1 again, it sounds like you have a basic misunderstanding of classes and what they can do for you. (This makes sense since you say you are "new to OOP".)

I am going to run afoul of terminology here unless I know which non-OOP languages you are familiar with, but I'll use a C example and deliberately gloss over a whole slew of issues, and claim that your class A is like a struct A, and your class B is just a struct B that contains an entire struct A:

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

If you make a new instance of a B, you can't make the type of its a member change, it's always going to be an actual A. Doesn't matter if there's a struct A2 (type or instance), the contents of a B includes exactly one A.

It sounds like what you want is not a subclass at all, but rather just an ordinary member, which (in C) is more like having a pointer to some other object, rather than incorporating it bodily:

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!'

(In C, having a pointer—at least, if it's void *—means you can point to whatever type you need to, or to nothing at all, just as a B above can be connected_to None instead of some A1 or A2, or indeed anything as long as it has .about().)

Given the above, you can then do:

>>> 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!
>>> 

and of course, you can make B's __init__ find an A1 or A2 (if one exists) on its own if passing it explicitly is not what you want.

This, of course, obscures what (sub)classes do do for you. Given your example above, you might create a class Maths(object) and then a sub-class Algebra(Maths), and maybe another sub-class Topology(Maths). Separately, you could create a class HumanLanguage(object) and a sub-class English(HumanLanguage), and another sub-class Russian(HumanLanguage). But you would not create a sub-class Ring(HumanLanguage), while Ring(Algebra) might make sense.


Edit to address Q3: in the interpreter you can see why printing super(B, self).__class__.__name__ only prints "super". Having done z = B():

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

Invoking super simply gets you this special proxy object. The proxy object is how instances can call "upwards" (technically, "mro"-wards); follow the links inside the Python2 docs.

于 2013-06-13T19:33:53.563 回答