类方法、静态方法

1. 类方法

  • 第一个形参是类对象的方法
  • 需要用装饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数。
class Dog(object):__type = "狗"# 类方法,用classmethod来进行修饰@classmethoddef get_type(cls):return cls.__type
print(Dog.get_type())
Copy

使用场景:

  • 当方法中 需要使用类对象 (如访问私有类属性等)时,定义类方法
  • 类方法一般和类属性配合使用

2. 静态方法

  • 需要通过装饰器@staticmethod来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)
  • 静态方法 也能够通过 实例对象类对象 去访问。
class Dog(object):type = "狗"def __init__(self):name = None# 静态方法    @staticmethoddef introduce():  # 静态方法不会自动传递实例对象和类对象print("犬科哺乳动物,属于食肉目..")dog1 = Dog()
Dog.introduce()    # 可以用 实例对象 来调用 静态方法
dog1.introduce()    # 可以用 类对象 来调用 静态方法
Copy

使用场景:

  • 当方法中 既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象 (如类属性、类方法、创建实例等)时,定义静态方法
  • 取消不需要的参数传递,有利于 减少不必要的内存占用和性能消耗

注意点:

  • 类中定义了同名的方法时,调用方法会执行最后定义的方法
class Dog:def demo_method(self):print("对象方法")@classmethoddef demo_method(cls):print("类方法")@staticmethoddef demo_method():  # 被最后定义print("静态方法")dog1 = Dog()
Dog.demo_method()  # 结果: 静态方法
dog1.demo_method()  # 结果: 静态方法

__new__和__init__方法

class A(object):def __init__(self):print("这是 init 方法")def __new__(cls):print("这是 new 方法")return object.__new__(cls)A()
Copy

总结

  • __new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供

  • __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例

  • __init__有一个参数self,就是这个__new__返回的实例,__init____new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

    单例设计模式

    举个常见的单例模式例子,我们日常使用的电脑上都有一个回收站,在整个操作系统中,回收站只能有一个实例,整个系统都使用这个唯一的实例,而且回收站自行提供自己的实例。因此回收站是单例模式的应用。

    确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,单例模式是一种对象创建型模式。

    # 实例化一个单例
    class Singleton(object):__instance = None__is_first = Truedef __new__(cls, age, name):if not cls.__instance:cls.__instance = object.__new__(cls)return cls.__instancedef __init__(self, age, name):if self. __is_first: # 不会再创建第二个对象self.age = ageself.name = nameSingleton. __is_first = Falsea = Singleton(18, "张三")
    b = Singleton(28, "张三")print(id(a))
    print(id(b))print(a.age) # 18
    print(b.age) # 18a.age = 19
    print(b.age)
    

继承的基本使用

程序里的继承

继承是面向对象软件设计中的一个概念,与多态、封装共为面向对象的三个基本特征。继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。

  • 在程序中,继承描述的是多个类之间的所属关系。
  • 如果一个类A里面的属性和方法可以复用,则可以通过继承的方式,传递到类B里。
  • 那么类A就是基类,也叫做父类;类B就是派生类,也叫做子类。
class Animal:def __int__(self):pass"""动物类"""def sleep(self):print('正在睡觉')class Dog(Animal):"""Dog类继承自Animal类"""def __init__(self):passclass Cat(Animal):  # 定义类时,在括号后面传入父类的类名,表示子类继承父类"""Cat类继承自Animal类"""def __int__(self):pass# Dog 和 Cat 都继承自Animal类,可以直接使用Animal类里的sleep方法
dog = Dog()
dog.sleep()cat = Cat()
cat.sleep()

在Python中,继承可以分为单继承、多继承和多层继承。

单继承:子类只继承一个父类

继承概念:子类用于父类的所有的方法和属性。

继承语法:

class 类名(父类名):pass
Copy
  • 子类继承自父类,可以享受父类中已经封装好的方法,不需要再次定义
  • 子类中应该根据职责,封装子类特有的属性和方法。

继承的传递性

Dog类继承自Animal,XiaoTianQuan又继承自Dog类,那么XiaoTianQuan类就具有了Animal类里的所有属性和方法。

子类拥有父类以及父类的父类中封装的所有属性和方法。

思考:

XiaoTianQuan能否调用Animal的run()方法? XiaoTianQUan能够调用Cat里的方法?

多继承

子类可以拥有多个父类,并且具有所有父类的属性和方法。

语法格式:

class 子类名(父类名1,父类名2...)pass
Copy

多继承的使用注意事项

思考:

如果不同的父类中存在同名的方法,子类对象在调用方法时,会调用哪个父类的方法? 说明:开发中,应该尽量避免这种容易产生混淆的情况。如果多个父类之间存在同名的属性后者方法,应该尽量避免使用多继承。

Python中的MRO

  • Python中针对类提供了一个内置属性__mro__可以用来查看方法的搜索顺序。
  • MRO 是method resolution order的简称,主要用于在多继承时判断方法属性的调用顺序。
print(C.__mro__)
Copy

输出结果:

(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
Copy
  • 在调用方法时,按照__mro__的输出结果从左至右的顺序查找。
  • 如果再当前类中找到方法,就直接执行,不再向下搜索。
  • 如果没有找到,就顺序查找下一个类中是否有对应的方法,如果找到,就直接执行,不再继续向下搜索。
  • 如果找到了最后一个类,依然没有找到方法,程序就会报错。

新式类和旧式(经典)类

object是Python中所有对象的基类,提供了一些内置的属性和方法,可以时候用dir函数查看。

  • 新式类:以object为基类的类,推荐使用
  • 经典类:不以object为基类的类,不推荐使用
  • 在 Python3.x 以后定义类时,如果没有指定父类,这个类会默认继承自 object,所以,python3.x版本定义的类都是新式类。
  • 在Python2.x中定义类时,如果没有指定父类,则不会继承自object.

为了保证代码在Python2.x和Python3.x中都能够运行,在定义类时,如果一个类没有父类,建议统一继承自’object’

class 类名(object):pass

对象相关的内置函数

Python中的身份运算符用来判断两个对象是否相等;isinstance用来判断对象和类之间的关系;issublcass用啊里判断类与类之间的关系。

身份运算符

身份运算符用来比较两个对象的内存地址,看这两个对象是否是同一个对象。

class Person(object):def __init__(self, name, age):self.name = nameself.age = agep1 = Person('张三', 18)
p2 = Person('张三', 18)
p3 = p1print(p1 is p2)  # False
print(p1 is p3)  # True
Copy

isinstance

instance内置函数,用来判断一个实例对象是否是由某一个类(或者它的子类)实例化创建出来的。

class Person(object):def __init__(self, name, age):self.name = nameself.age = ageclass Student(Person):def __init__(self, name, age, score):super(Student, self).__init__(name, age)self.score = scoreclass Dog(object):def __init__(self, name, color):self.name = nameself.color = colorp = Person('tony', 18)
s = Student('jack', 20, 90)
d = Dog('旺财', '白色')print(isinstance(p, Person))  # True.对象p是由Person类创建出来的
print(isinstance(s, Person))  # True.对象s是有Person类的子类创建出来的
print(isinstance(d, Person))  # False.对象d和Person类没有关系
Copy

issubclass

issubclass 用来判断两个类之间的继承关系。

class Person(object):def __init__(self, name, age):self.name = nameself.age = ageclass Student(Person):def __init__(self, name, age, score):super(Student, self).__init__(name, age)self.score = scoreclass Dog(object):def __init__(self, name, color):self.name = nameself.color = colorprint(issubclass(Student, Person))  # True
print(issubclass(Dog, Person))  # False

多态

面向对象的三大特性:

  • 封装:这是定义类的准则,根据对象的特点,将行为和属性抽象出来,封装到一个类中。
  • 继承:这是设计类的技巧。父类与子类,主要体现在代码的重用,不需要大量的编写重复代码。
  • 多态:不同的子类调用相同的父类方法,产生不同的执行结果,可以增加代码的外部灵活度。多态是以继承和重写父类方法为前提的,它是一种调用方法的技巧,不会影响到类的内部设计。

场景

  • 提供三个类:缉毒犬、军犬、人
  • 缉毒犬–>追查毒品,军犬–>攻击假人,人–>让小狗干活
  • 设计类来完成功能。

代码实现:

class ArmyDog(object):def bite_enemy(self):print('追击敌人')class DrugDog(object):def track_drug(self):print('追查毒品')class Person(object):def work_with_army(self, dog):dog.bite_enemy()def work_with_drug(self, dog):dog.track_drug()ad = ArmyDog()
dd = DrugDog()p = Person()
p.work_with_army(ad)
p.work_with_drug(dd)
Copy

思考:这段代码设是否有问题?

新增需求:此时,又多了一个犬种,就又需要在Person类里新建一个方法,让这个方法操作新的狗。

class XiaoTianDog(object):def eat_moon(self):print('哮天犬把月亮吃了')class Person(object):def work_with_xiaotian(self, dog):  # 添加方法dog.eat_moon()
Copy

Person 类总是不断的添加新的功能,每次都需要改动Person类的源码,程序的扩展性太差了!

  • 最好是提供一个父类 Dog,具备 work 的功能,其他小狗继承它,这样只要是小狗类,则行为被统一起来了,我们人类完全可以保证,只要是小狗的子类,找它干活肯定不会有问题。
  • 这样人只要一个方法就能逗任意种类的狗玩,哪怕是添加新的狗,人的类都不需要修改。
  • 图示如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EZa4xVQc-1610551511291)(imgs/使用多态.png)]

代码实现:

class Dog(object):def work(self):  # 父类提供统一的方法,哪怕是空方法passclass ArmyDog(Dog):   # 继承 Dogdef work(self):  # 子类重写方法,并且处理自己的行为print('追击敌人')class DrugDog(Dog):def work(self):print('追查毒品')class Person(object):def work_with_dog(self, dog):dog.work()    # 使用小狗可以根据对象的不同而产生不同的运行效果, 保障了代码的稳定性# 子类对象可以当作父类来使用
dog = Dog()
ad = ArmyDog()
dd = DrugDog()p = Person()
p.work_with_dog(dog)
p.work_with_dog(ad)  # 同一个方法,只要是 Dog 的子类就可以传递,提供了代码的灵活性
p.work_with_dog(dd)  # 并且传递不同对象,最终 work_with_dog 产生了不同的执行效果
Copy
  • 最终效果

    • Person 类中只需要调用 Dog 对象 work() 方法,而不关心具体是 什么狗
    • work() 方法是在 Dog 父类中定义的,子类重写并处理不同方式的实现
    • 在程序执行时,传入不同的 Dog 对象作为实参,就会产生不同的执行效果

多态总结

  • 定义:多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果
  • 好处:调用灵活,有了多态,更容易编写出通用的代码,做出通用的编程,以适应需求的不断变化!
  • 实现步骤:
    • 定义父类,并提供公共方法
    • 定义子类,并重写父类方法
    • 传递子类对象给调用者,可以看到不同子类执行效果不同

    后续更新:文件的操作

2021-18.面向对象进阶相关推荐

  1. 18. 面向对象进阶

    18. 面向对象进阶 目标:掌握面向对象进阶相关知识点,能沟通更加自如的使用面向对象来进行编程. 概要: 成员 变量 实例变量 类变量 方法 绑定方法 类方法 静态方法 属性 成员修饰符(公有/私有) ...

  2. Python之面向对象进阶

    Python之面向对象进阶 进阶有:Python 类的成员.成员修饰符.类的特殊成员. 一.类的成员 类的成员可以分为三大类:字段.方法和属性. 注:所有成员中,只有普通字段的内容保存对象中,即:根据 ...

  3. Day 23 面向对象进阶

    目录 面向对象进阶 类的继承 什么是继承 为什么要用继承 对象的继承 对象查找属性的顺序 类的派生 类的组合 菱形继承问题 类的分类 菱形继承问题 多态与多态性 多态 多态性 面向对象进阶 类的继承 ...

  4. JavaSE——面向对象进阶(封装、this、static、代码块、包、权限修饰符、main方法详解)

    第2节 面向对象进阶 一.封装与private 概述: 封装的意义在于保护或者防止代码(数据)被我们无意中破坏.保护成员属性,不让类以外的程序直接访问和修改. 封装原则: 隐藏对象的属性和实现细节,仅 ...

  5. Python面向对象进阶和socket网络编程

    写在前面 为什么坚持?想一想当初: 一.面向对象进阶 - 1.反射补充 - 通过字符串去操作一个对象的属性,称之为反射: - 示例1: class Chinese:def __init__(self, ...

  6. Java大数据-Week2-Day2面向对象进阶

    第二章第三节 面向对象进阶 文章目录 第二章第三节 面向对象进阶 前言 封装 this关键字 静态static 包 包2 权限修饰符 代码块 main方法详解 总结 前言 # 第三章第3节 面向对象进 ...

  7. python进阶课程目标 学习内容_Python学习教程(Python学习路线):第九天-面向对象进阶...

    面向对象进阶 在前面的章节我们已经了解了面向对象的入门知识,知道了如何定义类,如何创建对象以及如何给对象发消息.为了能够更好的使用面向对象编程思想进行程序开发,我们还需要对Python中的面向对象编程 ...

  8. Day09.面向对象进阶

    面向对象进阶 文章目录 面向对象进阶 前言 一. @property装饰器 二. \_\_slots\_\_魔法 三. 静态方法和类方法 四. 类之间的关系 五. 继承和多态 六. 综合案例 案例1: ...

  9. python进阶路线知乎_Python学习教程(Python学习路线):第九天-面向对象进阶

    面向对象进阶 在前面的章节我们已经了解了面向对象的入门知识,知道了如何定义类,如何创建对象以及如何给对象发消息.为了能够更好的使用面向对象编程思想进行程序开发,我们还需要对Python中的面向对象编程 ...

  10. Python基础内容训练11(面向对象进阶)

    面向对象进阶 一 综合案例 案例1 :简单的计算器 # 实现一个计算器可以进行简单的基本操作,以及打印结果def jia(n1, n2):return n1 + n2def jian(n1, n2): ...

最新文章

  1. 信息安全系统设计基础第六周学习总结—20135227黄晓妍
  2. Stumpwm的编译安装
  3. Codeforces Round #377 (Div. 2) 732A B C D E F
  4. SAP Fiori 3的暗黑主题,酷炫无比
  5. linux那些事之TLB(Translation-Lookaside Buffer)无效操作
  6. ZooKeeper--Recipes和解决方案
  7. 大道至简第二篇阅读笔记
  8. 如果您能天天读上一遍,就能和老外对话了!
  9. 圈子论坛社区小程序,交友,博客,社交,陌生人社交,即时聊天 前后端开源PHP
  10. Application.DoEvents()
  11. 机械制造作业考研题目答案分享——定位误差及其计算
  12. 【编译原理】 实验三 LL(1)分析法(LL1分析表的自动生成)
  13. java excel导出 jxl_JAVA利用JXL导出/生成 EXCEL
  14. 谷歌AIY项目深度揭秘:语音识别与视觉识别及神经网络AI工具!
  15. Tomcat启动项目警告: org.apache.jasper.servlet.TldScanner.scanJars 至少有一个JAR被扫描用于TLD但尚未包含TLD
  16. 如何优雅地打印Java数组?
  17. 手机号码格式正则表达式
  18. BIM综合软件:如何快速的给自己想要的构件填充颜色
  19. js 正则表达式(允许输入中文、英文、字母;汉字中间有空格;全部为相同数字;港澳台通行证、居住证)
  20. Android随笔-蓝牙

热门文章

  1. xp设置系统时间同步服务器,xp设置时间同步服务器
  2. 市面上比较好用的钣金展开软件都有哪些?
  3. css3弹性盒子居中总结1
  4. 动态渲染video视频
  5. mini计算机结构,通用解决方案:[教程信息]计算机主板ATX / Micro ATX / Mini-ITX的几种结构标准...
  6. Heat模板及简单应用
  7. 平板时代即将到来,写在即将发布Win8 Surface平板和iPad Mini之际
  8. Python Day 67 Dango框架图解(总结)、Wsgiref和uwsgi、前后端传输数据的编码格式、From表单和Ajax方式在前端往后端发送文件、补充一下页面清缓存...
  9. 换位思考的反思与总结
  10. [Java] Receipt 简易超市小票