继承与多肽

在面向对象的术语中,类当X扩展类Y时,则Y称为该等超级/父/基类,X称为子类/子/派生类。这里需要注意的一点是,只有数据字段和非专用的方法才能被子类访问。私有数据字段和方法只能在类中访问。

 

1,创建³³首先了一个名为Date的类,并将该对象作为参数传递,object是由Python中提供的内置类。创建³³之后了另一个名为time的类,并将Date类称为参数。通过这个调用,可以访问Date类中的所有数据和属性。正因为如此,的创建³³ Time类对象tm中父电子杂志类中get_date方法。

 

2,在Python中的中,类的构造函数用于创建对象(实例),并为属性赋值。

子类的构造函数总是调用父类的构造函数来初始化父类中的属性的值,然后它开始为其属性赋值。

 

3,在Python中的中,类的构造函数用于创建对象(实例),并为属性赋值。

子类的构造函数总是调用父类的构造函数来初始化父类中的属性的值,然后它开始为其属性赋值。

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

    def eat(self, food):
        print('%s is eating %s , '%(self.name, food))

class Dog(Animal):

    def fetch(self, thing):
        print('%s goes after the %s !'%(self.name, thing))


class Cat(Animal):

    def swatstring(self):
        print('%s shreds the string! ' % (self.name))


d = Dog('Ranger')
c = Cat("Meow")

d.fetch("ball");
c.swatstring()
d.eat("Dog food")
c.eat("Cat food")
## 调用一个没有的定义的方法
#d.swatstring()

在上面的例子中,我们看到如何父类中的属性或方法,以便所有的子类或子类都会从父类继承那些属性。

如果一个子类尝尝从另一个子类继承方法或数据,那么它将通过一个错误,就像看到当狗类尝试调用cat类有swatstring()方法时,它会抛出一个错误(AttributeError)。

 

我们用之前的继承示例理解多态的概念,并在两个子类中添加一个名为show_affection的常用方法 -

从这个例子可以看到,它指的是一种设计,其中不同类型的对象可以以相同的方式处理,或者更具体地说,两个或更多的类使用相同的名称或通用接口,因为同样的方法(下面的示例中的show_affection)用任何一种类型的对象调用

 

4,重载

在Python中,当子类包含一个覆盖超类方法的方法时,也可以通过调用超类方法 -

Super(Subclass, self).method而不是self.method

 

继承构造函数

从前面的继承示例中看到,__init__位于父类中,因为子类 - DogCat没有__init__方法.Python使用继承属性查找来查找动物类中的__init__

当我们创建子类时,首先它会查找dog类中的__init__方法,如果它找不到它,则查找父类Animal,并在那里找到并在那里调用它。

因此,当类设计变得复杂时,可能希望初始化一个实例,

首先通过父类构造函数然后通过子类构造函数处理它。

 


import random

class Animal(object):

    def __init__(self, name):
        self.name = name

class Dog(Animal):

    def __init__(self, name):
        super(Dog, self).__init__(name)
        self.breed = random.choice(['Doberman', 'German shepherd', 'Beagle'])

    def fetch(self, thing):
        print('%s goes after the %s !'%(self.name, thing))

d = Dog('黑皮')
print(d.name)
print(d.breed)

 

结论

  • __init__与任何其他方法一样; 它可以被继承

  • 如果一个类没有__init__构造函数,巨蟒将检查其父类查找。

  • 只要找到一个有__init__构造函数,巨蟒就会调用它并停止查找

  • 可以使用super()函数来调用父类中的方法。

  • 可能想要在父类以及子类进行初始化。

 

总结如下 -

  • 任何类都可以从多个类继承

  • 搜索继承类时,巨蟒通常使用“深度优先”顺序。

  • 但是,当两个类从同一个类继承时,巨蟒将从该MRO中消除该类的第一次出现

 

装饰器,静态和类方法

函数(或方法)由def语句创建³³³³。

虽然方法的工作方式与函数完全相同,除了方法第一个参数是实例对象的一点。

我们可以根据行为方式来分类方法

  • 简单的方法  - 在类的外部定义。该函数可以通过提供实例参数来访问类属性:
    def outside_func(():
    

    蟒蛇

  • 实例方法  -
    def func(self,)
    

    蟒蛇

  • 类方法  - 如果需要使用类属性
    @classmethod
    def cfunc(cls,)
    

    蟒蛇

  • 静态方法  - 没有关于该类的任何信息
    @staticmethod
    def sfoo()
    

    蟒蛇

     到目前为止,我们已经看到了实例方法,下面来了解其他两种方法。

类方法

@classmethod装饰器是一个内置的函数装饰器,它通过调用它的类或作为第一个参数调用的实例的类。评估结果会影响函数定义。

语法

class C(object):
   @classmethod
   def fun(cls, arg1, arg2, ...):
      ....
fun: function that needs to be converted into a class method
returns: a class method for function

蟒蛇

他们有权访问此cls参数,它不能修改对象实例状态。

  • 它受到类的约束,而不是类的对象。
  • 类方法仍然可以修改适用于类的所有实例的类状态。

2.静态方法

静态方法既不接受自己也不接受cls(class)参数,但可以自由接受任意数量的其他参数。

语法

class C(object):
   @staticmethod
   def fun(arg1, arg2, ...):
   ...
returns: a static method for function funself.

蟒蛇

  • 静态方法既不能修改对象状态,也不能修改类的状态。
  • 受限于可以访问的数据。

什么时候使用

  • 通常使用类方法来创建工厂方法。工厂方法返回不同用例的类对象(类似于构造函数)。
  • 通常使用静态方法来创建实用函数。

如图1所示,还有一种把数据和功能结合起来,用称为对象的东西包裹起来组织程序的方法。

类和对象是面向对象编程的两个主要方面。创建一个新类型,而对象这个类的实例。这类似于你有一个int类型的变量,这存储整数的变量是int类的实例(对象)。

 

类的方法与普通的函数只有一个特别的区别-它们必须有一个额外的第一个参数名称,但是调用在这个方法的时候你。为这个参数赋值,Python中会提供这个值这个特别的变量指对象本身,按照惯例它的名称是self

 

可以注意到存储对象的计算机内存地址也打印了出来。这个地址在你的计算机上会是另外一个值,因为Python中可以在任何空位存储对象。

 

在Python中的类中有很多方法的名字有特殊的重要意义。我们现在学习将__init__方法的意义。

__init__方法在类的一个对象被建立时,马上运行。这个方法可以用来对你的对象做一些你希望的初始化。注意,这个名称的开始和结尾都是双下划线。

 

 

这里,把我们__init__方法定义为取一个参数name(以及普通的参数self)。这个在__init__里,我们只是创建一个新的域,也称为name。注意它们是两个不同的变量,尽管它们有相同的名字。点号使我们能够区分它们。

最重要的是,没有我们专门调用__init__方法,只是在创建一个类的新实例的时候,把参数包括在圆括号内跟在类名后面,传递从而给__init__方法。这是这种方法的重要之处。

现在,能够我们在我们的方法中使用self.name域。在这sayHi方法中得到了验证。

 

当子类和父类都存在相同的run()方法时,我们说,子类的run()覆盖了父类的run(),在代码运行的时候,总是会调用子类的run()。这样,我们就获得了继承的另一个好处:多态。

 

要理解什么是多态,我们首先要对数据类型再作一点说明。当我们定义一个class的时候,我们实际上就定义了一种数据类型。我们定义的数据类型和Python自带的数据类型,比如str、list、dict没什么两样

a = list() # a是list类型
b = Animal() # b是Animal类型
c = Dog() # c是Dog类型

Dog可以看成Animal,但Animal不可以看成Dog

要理解多态的好处,我们还需要再编写一个函数,这个函数接受一个Animal类型的变量:

 

def run_twice(animal):
    animal.run()
    animal.run()

 

多态的好处就是,当我们需要传入DogCatTortoise……时,我们只需要接收Animal类型就可以了,因为DogCatTortoise……都是Animal类型,然后,按照Animal类型进行操作即可。由于Animal类型有run()方法,因此,传入的任意类型,只要是Animal类或者子类,就会自动调用实际类型的run()方法,这就是多态的意思:

对于Python这样的动态语言来说,则不一定需要传入Animal类型。我们只需要保证传入的对象有一个run()方法就可以了:

class Timer(object):
    def run(self):
        print('Start...')

 

继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写。

动态语言的鸭子类型特点决定了继承不像静态语言那样是必须的。

 

类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的 第一个参数名称

按照惯例它的名称是 self

#!/usr/bin/python
# -*- coding: UTF-8 -*-

class Employee:
   '''所有员工的基类'''
   empCount = 0

   def __init__(self, name, salary):
      self.name = name
      self.salary = salary
      Employee.empCount += 1

   def displayCount(self):
     print "Total Employee %d" % Employee.empCount

   def displayEmployee(self):
      print "Name : ", self.name,  ", Salary: ", self.salary

 

其中

  1. empCount 变量是一个类变量,它的值将在这个类的所有实例之间共享

    可以在内部类或外部类使用 Employee.empCount 访问

  2. init() 是一个特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法

  3. self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数

self 代表类的实例,而非类

类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的 第一个参数名称

按照惯例它的名称是 self

我们已经创建好了一个类 Employee,如果要创建这个类的实例,只需要使用 类名+() 即可

就像调用函数一样

类的实例会通过 __init__() 方法接受参数

 

垃圾回收机制不仅针对引用计数为 0 的对象,同样也可以处理循环引用的情况

循环引用指的是,两个对象相互引用,但是没有其他变量引用他们

这种情况下,仅使用引用计数是不够的

Python 的垃圾收集器实际上是一个引用计数器和一个循环垃圾收集器

作为引用计数的补充, 垃圾收集器也会留心被分配的总量很大 ( 及未通过引用计数销毁的那些 ) 的对象

在这种情况下, 解释器会暂停下来, 试图清理所有未引用的循环

 

# -*- coding: UTF-8 -*-

class Point:
   def __init__( self, x=0, y=0):
      self.x = x
      self.y = y
   def __del__(self):
      class_name = self.__class__.__name__
      print class_name, "销毁"

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值