一、上节补充

1、静态属性
静态属性 : 类的属性,所有的对象共享这个变量
  如果用对象名去修改类的静态属性:在对象的空间中又创建了一个属性,而不能修改类中属性的值
  操作静态属性应该用类名来操作

例1:请你写一个类,能够统计一共实例化了多少个对象?

class Foo:
count = 0
def __init__(self):
Foo.count += 1 f1 = Foo()
print(f1.count) #
f2 = Foo()
f3 = Foo()
f4 = Foo()
f5 = Foo()
print(f1.count) #
print(f5.count) #
print(Foo.count) #

结论:当类中的属性发生改变的时候,对象中没有同名的属性、方法的时候,对象使用属性名会跟着类中的变量走

例二:(类的静态属性为可变数据类型,对象也能引用并修改)

class Foo:
count = [0] f1 = Foo()
f1.count[0] += 1 # 静态属性的修改 1
print(f1.count[0]) # 对象引用类的静态属性 1
print(Foo.count[0]) # 类修改后 也是 1
f1.count = [2] # 对象新增 2
print(f1.count) #
print(Foo.count) # 类不变 1

结论:
1,类的静态属性是可变数据类型时,对象可以引用并修改
2,只要对象的某个属性被直接赋值,那么一定是对象的命名空间发生变化
3,只要是静态变量,就用类名操作

二、继承(提高代码的重用性,规范性)

(面向对象的三大特性:继承、多态、封装,这里先说一下继承)

(C语言没有面向对象,而java和C#只有单继承没有多继承(但是有接口),
python和C++有单继承也有多继承(python原本并没有接口,但是有些人为python开发了接口模块,所以在python中,
需要用接口的时候要安装特定的模块))

2-1单继承:
1,语法:
class A:
  pass

class B(A):
  pass

这就是单继承:
  A就叫:父类/超类/基类
  B就叫:子类/派生类

2,继承与重用:子类可以使用父类中的变量和方法
下面看个例子了解一下:
我们都知道猫有自己的名字和吃的粮食,还有猫会喝水吃东西,抓老鼠等,
狗也有自己的名字和吃的粮食,狗也会喝水吃东西,狗还能看家等。
因此构建出来的类如下:

class Cat():
def __init__(self,name,food):
self.name = name
self.food = food def eat(self):
print('吃猫粮') def drink(self):
print('喝水') def catch_mouse(self):
print('抓老鼠') class Dog():
def __init__(self,name,food):
self.name = name
self.food = food def eat(self):
print('吃狗粮') def drink(self):
print('喝水') def look_after_house(self):
print('看家') xiaomao = Cat('啊猫','猫粮')
print(xiaomao.name) #啊猫
xiaomao.eat() #吃猫粮
xiaomao.catch_mouse() #抓老鼠 xiaogou = Dog('啊狗','狗粮')
print(xiaogou.name) #啊狗
xiaogou.eat() #吃狗粮
xiaogou.look_after_house() #看家

这么一看是不是感觉代码有很多重复的地方,比如初始化名字和食物、吃东西和喝水的方法,
那么怎么样可以节省代码呢?这就要用到继承。
我们先定义一个公共的类Animal,用来存储猫和狗相同的方法和属性。猫类和狗类分别继承Animal类,
就可以继承Animal的属性和方法了。

class Animal:
def __init__(self,name,food):
self.name = name
self.food = food def eat(self):
print('吃%s'%(self.food)) def drink(self):
print('喝水') class Cat(Animal): def catch_mouse(self):
print('抓老鼠') class Dog(Animal): def look_after_house(self):
print('看家') xiaomao = Cat('啊猫','猫粮')
print(xiaomao.name) #啊猫
xiaomao.eat() #吃猫粮
xiaomao.catch_mouse() #抓老鼠 xiaogou = Dog('啊狗','狗粮')
print(xiaogou.name) #啊狗
xiaogou.eat() #吃狗粮
xiaogou.look_after_house() #看家

这样一来是不是就简化了很多,而且再来一个猪类,只要它也是有这些公共方法,它也能继承Animal类,
一下子就可以节省了很多代码。

其中:
父类/超类/基类 :Animal
子类/派生类 :Cat、Dog

3,继承与派生:
(1)继承:提高代码的重用性,规范代码
(2)派生:子类在父类的基础上又新创建了自己需要的方法和属性
(3)父类有的而子类没有:子类对象直接调用 就会直接执行父类的方法
(4)父类有的而子类也有:1、子类对象调用 直接执行子类中的方法
            2、想在子类中使用父类的名字:父类名、super()去调用

例如:

class Animal:
def __init__(self, name, food):
self.name = name
self.food = food def eat(self):
print('吃%s' % (self.food)) def drink(self):
print('喝水') class Cat(Animal): # Animal的派生类
def __init__(self, name, food, eye_color):
self.eye_color = eye_color # 派生属性
super().__init__(name, food)
# Animal.__init__(self,name,food) 跟上一句super()都是调用父类的方法
# 不同的是super()不需要传self,而直接用父类名.方法(),需要传self def catch_mouse(self): # 派生方法
print('抓老鼠') def eat(self): # 不仅执行了父类中的基础功能,还完成了特殊的功能
Animal.eat(self)
# super().eat()
self.weight = 10 class Dog(Animal):
def look_after_house(self):
print('看家') def eat(self):
# Animal.eat(self)
super().eat()
self.drink() # 吃完东西调用父类喝水的方法 xiaomao = Cat('阿猫', '猫粮', '绿色')
print(xiaomao.eye_color) # 绿色
print(xiaomao.food) #猫粮
xiaomao.catch_mouse() #抓老鼠
xiaomao.eat() #吃猫粮
print(xiaomao.weight) # xiaogou = Dog('啊狗', '狗粮')
xiaogou.eat() #吃狗粮 喝水

2-2多继承:
1,语法:
class A:
  pass

class B:
  pass

class C(A,B):
  pass

C既继承了A,又继承了B

2,实例:

# 天鹅:飞 游泳 走路
# 老虎:走路 游泳
# 鹦鹉:飞 说话 走路 class Animal:
def __init__(self,name):
self.name = name class FlyAnimal(Animal): #会飞的动物类
def fly(self):
print('%s在飞' % self.name) class WalkAnimal(Animal): #会走路的动物类
def walk(self):
print('%s在走路'%self.name) class SwimAnimal(Animal): #会游泳的动物类
def swim(self):
print('%s在游泳'%self.name) class Tiger(SwimAnimal,WalkAnimal): # 老虎
pass class Swan(SwimAnimal,WalkAnimal,FlyAnimal): # 天鹅
pass class Parrot(FlyAnimal,WalkAnimal): # 鹦鹉
def talk(self):
print('%s说话了'%self.name) swan = Swan('天鹅')
swan.fly() # 天鹅在飞
swan.walk() # 天鹅在走路

三、抽象类

1、python3中的抽象类

抽象类是一个规范,它基本不会实现什么具体的功能,只能被继承,不能被实例化

abc:Abstract Base Classes

作用:在代码中定义和使用抽象基类进行API检查

1、抽象类的作用:规范编程模式
  多人开发、复杂的需求、后期的扩展
  是一种用来帮助我们完成规范化的手段

2、如何定义抽象类
  1,from abc import ABCMeta,abstractmethod
  2,在这个类创建的时候指定 metaclass = ABCMeta
  3,在你希望子类要实现的方法的上一行加上一个 @abstractmethod装饰器

3、使用抽象类
  1,继承这个类
  2,必须实现这个类中被@abstractmethod装饰器装饰的方法

4、实例

# 支付功能

from abc import ABCMeta, abstractmethod
class Payment(metaclass=ABCMeta): # 模板的功能
@abstractmethod # abstractmethod是一个装饰器,装饰器怎么用?放在函数或者类的上一行
def pay(self): pass # 这样就构建了一个抽象类Payment,并声明了子类必须要实现的方法是 pay(),若子类没有定义pay(),则实例化时会报错 class Alipay(Payment): # 继承了抽象类,就必须实现抽象类中被@abstractmethod装饰器装饰的方法 pay()
def pay(self, money):
print('使用支付宝支付了%s元' % money) class Wechatpay(Payment):
def pay(self, money):
print('使用微信支付了%s元' % money) class My_pay(Payment): # 这里没有定义pay()方法,那么在实例化的时候机会报错
def fuqian(self,money):
print('你支付了%s元' % money) def pay(obj, money):
obj.pay(money) # p = Payment() # 报错 抽象类不能被实例化 a = Alipay()
# a.pay(100)
pay(a,100) # 使用支付宝支付了100元 we = Wechatpay()
# we.pay(200)
pay(we,200) # 使用微信支付了200元 my = My_pay() # 报错:类中没有定义抽象类的pay方法
pay(my,300)

5、如果你的规范中还包括属性,那么你可以使用 @abstractproperty来定义

from abc import ABCMeta, abstractproperty, abstractmethod

class Base(metaclass=ABCMeta):
@abstractproperty
def value(self):
pass @abstractmethod
def pay(self):
pass class Zhifubao(Base):
@property
def value(self):
return 'value' def pay(self):
return "pay" z = Zhifubao()
print(z.value)

6、类似的还有 类方法@abstractclassmethod,静态方法 @abstractstaticmethod

2、python2中的抽象类

2-1、python2和python3都兼容的写法

上面python3的写法只适用于python3,下面这种写法,python2和3都适用

from abc import ABCMeta, abstractmethod

class Payment(object):
__metaclass__ = ABCMeta @abstractmethod
def pay(self, money):
pass class Alipay(Payment): # 继承了抽象类,就必须实现抽象类中被@abstractmethod装饰器装饰的方法 pay()
def pay(self, money):
print('使用支付宝支付了%s元' % money)

2-2、使用six模块,也适用于python2和3

import six
from abc import ABCMeta, abstractmethod @six.add_metaclass(ABCMeta)
class Payment(object):
# __metaclass__ = ABCMeta @abstractmethod
def pay(self, money):
pass class Alipay(Payment): # 继承了抽象类,就必须实现抽象类中被@abstractmethod装饰器装饰的方法 pay()
def pay(self, money):
print('使用支付宝支付了%s元' % money)

四、新式类

1、新式类和经典类:
继承了object的类就是新式类
在py3中默认都继承了object因此所有的类都是新式类
在py2中既有新式类又有经典类

python3.x:
在python3.x版本中所有的类都是新式类
所有的新式类都有一个默认的父类 : object

class Person1:pass
class Person2():pass
class Person3(object):pass
# __bases__方法是查看某个类继承的所有父类
print(Person1.__bases__)  # (<class 'object'>,)
print(Person2.__bases__)  # (<class 'object'>,)
print(Person3.__bases__)  # (<class 'object'>,)

python 2.7:
经典类和新式类并存
class Student:pass # 经典类
class Student(object):pass # 新式类

class Person1:pass # 经典类
class Person2():pass #经典类
class Person3(object):pass #新式类

2、多继承的顺序(在新式类和经典类之间的区别)
新式类
  所有的多继承关系寻找方法的顺序 :遵循广度优先算法
  继承object
  类名.mro() # (返回一个类的寻找顺序(继承顺序)的列表)
  super : super不是单纯的找父类,而是遵循mro顺序的

经典类
  python2.x
  不主动继承object
  经典类在找父类中方法的过程中遵循:深度优先算法
  不提供mro方法和super

2-1、新式类中

class A:
def func(self):
print('A') class B(A):
def func(self):
super().func()
print('B') class C(A):
def func(self):
super().func()
print('C') class D(B,C):
def func(self):
super().func()
print('D')
print(D.mro()) # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
D().func() # A C B D

class A:
pass class B(A):
pass class C(A):
pass class D(B):
pass class E(C):
pass class F(D,E):
pass print(F.mro())
结果:
# [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>,
<class '__main__.A'>, <class 'object'>]

python之继承、抽象类、新式类和经典类的更多相关文章

  1. Python中新式类和经典类的区别,钻石继承

    1)首先,写法不一样: class A: pass class B(object): 2)在多继承中,新式类采用广度优先搜索,而旧式类是采用深度优先搜索. 3)新式类更符合OOP编程思想,统一了pyt ...

  2. Python类总结-继承-子类和父类,新式类和经典类

    子类和父类 class Father(object): #子类在使用super调用父类时,Father后面要加object --新式类 def __init__(self): self.Fname = ...

  3. 继承 派生 super()经典类 新式类

    '''1什么是继承? 继承一种新建类的方式,在python中支持一个儿子继承多个爹 新建的类称为子类的或者派生类 父类有可以称为基类或者超类 子类会‘遗传’父类的属性 2 为什么要用继承 减少代码冗余 ...

  4. python中新式类和经典类的区别

    1).python在类中的定义在py2-3版本上是使用的有新式类和经典类两种情况,在新式类和经典类的定义中最主要的区别是在定义类的时候是否出现引用object;如:经典类:Class 类名::而新式类 ...

  5. Python新式类与经典类的区别

    1.新式类与经典类 在Python 2及以前的版本中,由任意内置类型派生出的类(只要一个内置类型位于类树的某个位置),都属于“新式类”,都会获得所有“新式类”的特性:反之,即不由任意内置类型派生出的类 ...

  6. python中的__new__与__init__,新式类和经典类(2.x)

    在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A()) 新式类跟经典类的差别主要是以下几点: 1 ...

  7. python中新式类和经典类

    python中的类分为新式类和经典类,具体有什么区别呢?简单的说, 1.新式类都从object继承,经典类不需要. Python 2.x中默认都是经典类,只有显式继承了object才是新式类 Pyth ...

  8. Python新式类和经典类的区别

    @Python新式类和经典类的区别 class ClassicClass(): pass class NewStyleClass(object): pass x1 = ClassicClass() x ...

  9. python基础===新式类与经典类

    首先: Python 2.x中默认都是经典类,只有显式继承了object才是新式类 Python 3.x中默认都是新式类,不必显式的继承object 这两种类的区别: 新式类重定义的方法更多,当然这不 ...

随机推荐

  1. 坑:微信小程序wx.request和wx.uploadFile中传参数的区别

    微信小程序中通过组件<form>提交表单的时候,在js中通过e.detail.value得到所提交表单的json格式数据.一般提交表单我们都是通过wx.request请求,提交表单数据,通 ...

  2. java对接申通下单接口示例代码

    上面是控制台示例代码 public class Sample{ private final static String URL = "http://order.sto-express.cn: ...

  3. 如何在linux下使用sudo命令不用输入密码

    用过linux的小伙伴可能都知道,每次使用sudo的时候需要输入密码,这样很耽误事,那么接下来我会教大家如何去设置 一.1.输入su root进入root模式 2.输入visudo会打开/etc/su ...

  4. ASP.NET Core 入门教程 6、ASP.NET Core MVC 视图布局入门

    一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)视图母版页教程 ASP.NET Core MVC (Razor)带有Section的视图母版页教程 ASP.NET Cor ...

  5. Linux压缩打包tar命令总结

      命令简介   在Linux系统的维护.管理中,tar命令是一个使用频率很高的命令,tar命令的功能主要是将众多文件打包成一个tar文件并压缩,并且能保持文件的权限属性.tar其实最开始是用来做磁带 ...

  6. Asp.net Core应用程序部署为服务

    安装前使用dotnet命令运行下看网站能不能正常运行 1.下载nssm,下载后解压文件 下载地址:https://nssm.cc/usage 2.使用命令行工具进入到nssm的目录: 3.执行服务安装 ...

  7. python正则表达式相关记录

    1 python中字符串前加‘r’,即可阻止‘\’导致的字符转义.但是在re.sub()中参数中加'r'不会起作用.

  8. 【任务】Python语言程序设计.MOOC学习

    [博客导航] [Python导航] 任务 18年11月29日开始,通过9周时间跨度,投入约50小时时间,在19年1月25日之前,完成中国大学MOOC平台上的<Python语言程序设计>课程 ...

  9. JavaScript数据类型之null和undeined

    null null是JavaScrpt的关键字,表示一个特殊值,常用于描述"空值".对null执行typeof运算将返回字符串"object". undefin ...

  10. 爬虫系列二(数据清洗--->xpath解析数据)

    一 xpath介绍 XPath 是一门在 XML 文档中查找信息的语言.XPath 用于在 XML 文档中通过元素和属性进行导航. XPath 使用路径表达式在 XML 文档中进行导航 XPath 包 ...