When you are doing this kind of specialization, there are three ways that the parent and child classes can interact:
# 当你在做这种专业化的工具的时候, 有三种父类和子类可以继承的方式.
\1. Actions on the child imply an action on the parent.
# 在子类上的操作意味着对父类的操作
\2. Actions on the child override the action on the parent.
# 在子类上的操作会覆盖在父类上的操作
\3. Actions on the child alter the action on the parent.
# 在子类上的操作会改变父类上的操作
I will now demonstrate each of these in order and show you code for them.
# now I will (in order) demonstrate each of these
# 现在我会依次演示它们中的每一个,并给你看它们的代码


Implicit Inheritance 隐式继承

First I will show you the implicit actions that happen when you define a function in the parent but *not* in the child.
# 首先我会向你展示当你定义一个方法在父函数中而不是子函数时会发生的隐式操作.
class Parent(object):
# 隐式
def implicit(self):
print("PARENT implicit()")

class Child(Parent):
pass

dad = Parent()
son = Child()

dad.implicit()
son.implicit()

The use of pass under the class Child: is how you tell Python that you want an empty block. 
# 在类Child的下方使用pass: 这正是你告诉python你想要一个空模块

This creates a class named Child but says that there’s nothing new to define in it.
# 这里创建了一个新的类叫做Child, 但其中并没有任何新的东西需要定义

Instead it will inherit all of its behavior from Parent.
# 反而,他会从Parent继承所有的行为.

When you run this code you get the following:
# 当你运行这些代码的时候你会得到如下结果:
$ python3.6 ex44a.py
PARENT implicit()
PARENT implicit()
Notice how even though I’m calling son.
# 注意看我即使是正在调用son实例

implicit() on line 13 and even though Child does not have an implicit function defined,
# 第13行中的implicit() 即使Child没有一个隐式的方法被定义

it still works, and it calls the one defined in Parent.
# 他仍然起作用了, 并且它调用了Parent中被定义的方法

This shows you that if you put functions in a base class (i.e., Parent),
# 这表明 如果你把方法放进一个诸如(Parent())的类中,

then all subclasses (i.e., Child) will automatically get those features.
# 那么所有的子类,比如(Child)会自动获得这些功能,

Very handy for repetitive code you need in many classes.
# 当你需要在类中写很多重复性的代码时非常有用


Override Explicitly 显式重写

The problem with having functions called implicitly is sometimes you want the child to behave differently.
# 有时你想要child表现得不同一些,这里会有一个隐式调用的问题
# 隐式调用函数的问题在于,有时你想要child表现得不同

In this case you want to override the function in the child,
# 在这个例子中,你想要的覆盖child中的函数

effectively replacing the functionality.
# 有效地替换函数

To do this just define a function with the same name in Child. Here’s an example:
# 想要做到它,只需要定义一个在Child类中有相同名字的函数. 这里有一个例子:
class Parent(object):

def override(self):
print("PARENT override()")

class Child(Parent):

def override(self):
print("Child override()")

dad = Parent()
son = Child()

dad.override()
son.override()
(venv) C:\work>python ex44b.py
PARENT override()
Child override()
As you can see, when line 14 runs, it runs the Parent.
# 你可以看到, 当地十四行运行的时候,它运行了Parent类

override function because that variable (dad) is a Parent.
# 覆盖了方法,因为变量dad是类的实例

But when line 15 runs, it prints out the Child.
# 但是当运行到15行时, 它打印出了Child

override messages because son is an instance of Child and Child overrides that function by defining its own version.
# 覆盖了信息.因为son是Child中的一个实例.并且Child通过定义他自己的方法,覆盖了原本的函数

Take a break right now and try playing with these two concepts before continuing
# 休息一下现在, 并在继续之前尝试了解以下两个概念


Alter Before or After

The third way to use inheritance is a special case of overriding where you want to alter the behavior before
or after the Parent class’s version runs.
# 使用继承的第三种方法是覆盖的特殊情况,即您希望在父类版本运行之前或之后更改行为。

You first override the function just like in the last example, but
then you use a Python built-in function named super to get the Parent version to call.
# 首先,就像在上一个例子中,你覆盖了函数,但之后你使用了python的一个名叫super内置函数来调用父版本.


Here’s the example of doing that so you can make sense of this description:
# 下面是一个例子,这样你就能理解这个描述了:
class Parent(object):
# 父类有一个方法叫altered
def altered(self):
print("PARENT altered()")

class Child(Parent):
# 子类也有一个方法叫altered
def altered(self):
print("CHILD, BEFORE PARENT altered()")
super(Child, self).altered()
print("CHILD, AFTER PARENT altered()")

dad = Parent()
son = Child()

dad.altered()
son.altered()

The important lines here are 9–11, where in the Child I do the following when son.altered() is called:

# 9-11行比较重要, 在Child中,当我调用son.altered()时,执行以下操作:
1. Because I’ve overridden Parent.altered the Child.altered version runs, and line 9 executes like you’d expect.
#
2. In this case I want to do a before and after, so after line 9 I want to use super to get the Parent.altered version.

3. On line 10 I call super(Child, self).altered(), which is aware of inheritance and will get the Parent class for you.

You should be able to read this as “call super with arguments Child and self, then call the function altered on whatever it returns.”
# 你应该把他理解为 :使用参数Child和self来执行super,然后调用altered(),不管他返回什么

4. At this point, the Parent.altered version of the function runs, and that prints out the Parent
message.

5. Finally, this returns from the Parent.altered, and the Child.altered function continues
to print out the after message.



If you run this, you should see this:

(venv) C:\work>python ex44c.py
PARENT altered()

CHILD, BEFORE PARENT altered()
PARENT altered()
CHILD, AFTER PARENT altered()


All Three Combined

To demonstrate all of these, I have a final version that shows each kind of interaction from inheritance in one file:

ex44d.py

class Parent(object):
# 父类的override方法
def override(self):
print("PARENT override()")
# 父类的implicit方法 # 未被子类覆盖
def implicit(self):
print("PARENT implicit()")
# 父类的altered方法
def altered(self):
print("PARENT altered()")

# 子类
class Child(Parent):
# 子类的override方法 覆盖了父类的override
def override(self):
print("CHILD override()")
# 子类的altered方法 覆盖了父类的altered方法
def altered(self):
print("CHILD, BEFORE PARENT altered()")
# 继承了父类的altered()方法
super(Child, self).altered()
print("CHILD, AFTER PARENT altered()")

# 实例生成
dad = Parent()
son = Child()

# 调用方法
dad.implicit()
son.implicit() # 未被覆盖

dad.override()
son.override() # 覆盖了

dad.altered()
son.altered() # 覆盖了dad得altered()方法 用super继承

Go through each line of this code, and write a comment explaining what that line does and whether it’s
an override or not.
Then run it and confirm you get what you expected
# 遍历每一行的代码, 并为这一行做了什么和是否它覆盖了写一段注释.
# 然后运行它 并确认你得到了你所期望的

(venv) C:\work>python ex44d.py
PARENT implicit()
PARENT implicit()
PARENT override()
CHILD override()
PARENT altered()
CHILD, BEFORE PARENT altered()
PARENT altered()
CHILD, AFTER PARENT altered()


The Reason for super()

This should seem like common sense, but then we get into trouble with a thing called multiple inheritance.
# 这似乎是常识, 但随后我们遇到了一个叫做多继承的麻烦

Multiple inheritance is when you define a class that inherits from one or more classes, like this:
# 多继承是当你定义一个继承自一个或多个类的clas时,像这样:

class SuperFun(Child, BadStuff):
pass
This is like saying, “Make a class named SuperFun that inherits from the classes Child and BadStuff at the same time.”
这就好像在说, "创建一个叫SuperFun的类 同时继承Child和BadStuff类"

In this case, whenever you have implicit actions on any SuperFun instance,
# 在这种情况下, 无论你在SuperFun的实例上有多少个隐式动作时

Python has to look up the possible function in the class hierarchy for both Child and BadStuff,
Python必须在类层次结构中查找可能的函数,包括Child和bad,

but it needs to do this in a consistent order.
# 但是它需要按照一致的顺序来做

do this Python uses “method resolution order” (MRO) and an algorithm called C3 to get it straight.
# 为了做到这一点,Python使用了“方法解析顺序”(MRO)和一个称为C3的算法


Because the MRO is complex and a well-defined algorithm is used, Python can’t leave it to you to get the MRO right.

Instead, Python gives you the super() function, which handles all of this for you in the places that you need the altering type of actions as I did in Child.altered.

With super() you don’t have to worry about getting this right, and Python will find the right function for you.

因为MRO是复杂的,并且使用了定义良好的算法,所以Python不能让您来获得正确的MRO。

相反,Python提供了super()函数,它在需要更改操作类型的地方为您处理所有这些操作,就像我在child.altered 中所做的那样。

使用super(),您不必担心如何正确地实现这个函数,Python将为您找到正确的函数


Using super() with init

The most common use of super() is actually in __init__ functions in base classes. This is usually
the only place where you need to do some things in a child, then complete the initialization in the parent.
Here’s a quick example of doing that in the Child:

实际上,super()最常见的用法是在基类中的剩余init__函数中。
这通常是惟一需要在子程序中执行某些操作,然后在父程序中完成初始化的地方。
这里有一个在孩子身上做的简单例子:
class Child(Parent):
def __init__ (self, stuff):
self.stuff = stuff
super(Child, self).__init__()


Composition

Inheritance is useful, but another way to do the exact same thing is just to use other classes and modules,
rather than rely on implicit inheritance. If you look at the three ways to exploit inheritance, two of the three
involve writing new code to replace or alter functionality. This can easily be replicated by just calling
functions in a module. Here’s an example of doing this:

继承是有用的,但是做同样事情的另一种方法是仅仅使用其他类和模块,而不是依赖隐式继承。
如果您查看利用继承的三种方法,其中两种涉及编写新代码来替换或更改功能。
只需调用模块中的函数就可以轻松地复制这一点。
这里有一个这样做的例子:

ex44e.py

class Other(object):

def override(self):
print("OTHER override()")

def implicit(self):
print("OTHER implicit()")

def altered(selfs):
print("OTHER altered()")

class Child(object):

# 自带属性
def __init__(self):
# o生成一个实例叫other 作为属性,赋值给Child实例
self.other = Other()

# 定义方法implict() 覆盖父类implict()
def implicit(self):
# 调用child实例的other实例的方法implicit()
self.other.implicit()

# 方法覆盖父类的override
def override(self):
print("CHILD override()")

# 覆盖父类
def altered(self):
print("CHILD, BEFORE OTHER altered()")
# 调用 other实例的altered()方法
self.other.altered()
print("CHILD, AFTER OTHER altered()")


son = Child()

son.implicit()
son.override()
son.altered()

In this code I’m not using the name Parent, since there is not a parent-child is-a relationship. This is
a has-a relationship, where Child has-a Other that it uses to get its work done. When I run this I get
the following output:

在此代码中,我没有使用名称Parent,因为没有父子is-a关系。这是一个has-a关系,其中Child有一个Other来完成它的工作。当我运行这个,我得到如下输出:

(venv) C:\work>python ex44e.py
OTHER implicit()
CHILD override()
CHILD, BEFORE OTHER altered()
OTHER altered()
CHILD, AFTER OTHER altered()
You can see that most of the code in Child and Other is the same to accomplish the same thing. 

The only difference is that I had to define a Child.implicit function to do that one action.

I could then ask myself if I need this Other to be a class, and could I just make it into a module named other.py?

您可以看到,Child和Other中的大部分代码都是相同的,可以完成相同的事情。
唯一的区别是我必须定义一个孩子。隐函数来做这个动作。

然后我可以问自己,我是否需要这个其他的是一个类,我是否可以把它放到一个名为Other .py的模块中?


When to Use Inheritance or Composition

The question of “inheritance versus composition” comes down to an attempt to solve the problem of
reusable code. You don’t want to have duplicated code all over your software, since that’s not clean and
efficient. Inheritance solves this problem by creating a mechanism for you to have implied features in
base classes. Composition solves this by giving you modules and the capability to call functions in other
classes.

继承还是组合”的问题归结为试图解决可重用代码的问题。您不希望在您的软件上到处都有重复的代码,因为这样做不干净,也不高效。
继承通过在基类中创建一种具有隐含特性的机制来解决这个问题。
复合为您提供了模块和调用其他类中的函数的能力,从而解决了这个问题.
If both solutions solve the problem of reuse, then which one is appropriate in which situations? The
answer is incredibly subjective, but I’ll give you my three guidelines for when to do which:

如果这两种解决方案都解决了重用的问题,那么哪种方案在哪种情况下合适呢?这个问题的答案是非常主观的,但是我会告诉你我的三个指导原则:
1. Avoid multiple inheritance at all costs, as it’s too complex to be reliable. If you’re stuck with
it, then be prepared to know the class hierarchy and spend time finding where everything is
coming from.
2. Use composition to package code into modules that are used in many different unrelated places
and situations.
3. Use inheritance only when there are clearly related reusable pieces of code that fit under a
single common concept or if you have to because of something you’re using.

#1. 尽量避免多重继承,因为它太复杂而不可靠。如果您被它困住了,那么请准备好了解类层次结构并花时间查找所有内容的来源
#2.使用组合将代码打包到模块中,用于许多不同的不相关的地方和情况。
#3. 只有当有明确相关的可重用代码片段符合单一公共概念时,或者当你不得不使用某些东西时,才使用继承。
Do not be a slave to these rules. The thing to remember about object-oriented programming is that it
is entirely a social convention programmers have created to package and share code. Because it’s a
social convention, but one that’s codified in Python, you may be forced to avoid these rules because of
the people you work with. In that case, find out how they use things and then just adapt to the situation.

不要做这些规则的奴隶。关于面向对象编程,需要记住的是,它完全是程序员为打包和共享代码而创建的一种社会惯例。因为这是一种社会惯例,但是是用Python编写的,所以您可能会因为与您一起工作的人而被迫避免这些规则。在这种情况下,找出他们如何使用事物,然后适应环境


Study Drills

There is only one Study Drill for this exercise because it is a big exercise. Go and read http://www

.python.org/dev/peps/pep-0008/ and start trying to use it in your code. You’ll notice that some of it is

different from what you’ve been learning in this book, but now you should be able to understand their

recommendations and use them in your own code. The rest of the code in this book may or may not

follow these guidelines depending on whether it makes the code more confusing. I suggest you also do

this, as comprehension is more important than impressing everyone with your knowledge of esoteric

style rules.

这个练习只有一个学习练习,因为它是一个大练习。去看看http://www
。python.org/dev/peps/pep-0008/,并开始尝试在代码中使用它。您会注意到其中一些内容与您在本书中所学的内容有所不同,但是现在您应该能够理解他们的建议并在自己的代码中使用它们。本书的其余代码是否遵循这些指导原则取决于它是否使代码更加混乱。我建议你也这样做,因为理解比用你的e知识给别人留下深刻印象更重要


Common Student Questions

我怎样才能更好地解决以前没有遇到过的问题呢?

How do I get better at solving problems that I haven’t seen before?

The only way to get better at solving problems is to solve as many problems as you can by yourself. Typically people hit a difficult
problem and then rush out to find an answer. This is fine when you have to get things done, but
if you have the time to solve it yourself, then take that time. Stop and bang your head against
the problem for as long as possible, trying every possible thing, until you solve it or give up.
After that the answers you find will be more satisfying, and you’ll eventually get better at solving
problems.

更好地解决问题的唯一方法就是自己解决尽可能多的问题。通常人们遇到一个难题,然后冲出去寻找答案。当你必须把事情做完的时候,这很好,但是如果你有时间自己解决它,那么就花时间。停下来,尽可能长时间地用你的脑袋去思考这个问题,尝试所有可能的事情,直到你解决了它或者放弃。
在那之后,你找到的答案会更令人满意,最终你会更善于解决问题

Aren’t objects just copies of classes?

In some languages (like JavaScript) that is true. These are
called prototype languages, and there are not many differences between objects and classes
other than usage. In Python, however, classes act as templates that “mint” new objects, similar
to how coins are minted using a die (template).

对象不就是类的副本吗?

在某些语言中(如JavaScript)是这样的。这些被称为原型语言,除了用法之外,对象和类之间没有太多区别。然而,在Python中,类充当“铸造”新对象的模板,类似于使用die(模板)铸造硬币。