Python回顾面向对象

【一】面向过程开发和面向对象开发

【1】面向过程包括函数和面条

  • 包括面条版本一条线从头穿到尾
  • 学习函数后开始对程序进行分模块,分功能开发
  • 学习模块化开发,我们就可以对我们的功能进行分类开发
  • 建一个功能的包---->在模块(py)文件中开发相应的功能 ---->通过包的init文件将我们想对外开放的功能导出去 ATM的分层,易于扩展和开发

【2】面向对象开发

  • 将一类的功能和数据整合到一起就是---类
  • 通过实例化类能得到相应的对象---不仅包括了所有的公共部分,还可以自定制对象的属性和方法

【二】什么是类,什么是对象

【1】类的演示

  • 类就是数据和程序的结合体
  • 对象是类的具体实现
# 动物类---》猫类 这是一个简单的 Python 类 MyCat,具有一个构造方法 __init__。这个类表示猫的实体,每只猫有一个名字和颜色。__init__ 方法是一个特殊的方法,用于初始化对象的属性。在这里,它接受两个参数 name 和 color,并将它们分别赋值给实例属性 self.name 和 self.color。如果不提供初始化方法 __init__ 或者提供的初始化方法中没有对属性进行赋值,那么创建类的实例时,实例将没有任何属性。这可能会导致在访问实例属性时出现 AttributeError,因为属性没有被定义。 # object(新式类) class MyCat(object): def __init__(self, name, color): # 对属性进行赋值 self.name = name self.color = color class Cat(object): mycat = "小猫咪" def __init__(self, name, color): self.name = name self.color = color def read(self): print(f'{self.name} is {self.color}') obj = Cat(name="xiaomi", color='yello') obj.read()

【2】对象的演示

(1)__init__的四部推导过程

(2)实例化类得到对象

class MyCat(object): def __init__(self, name, color): self.name = name self.color = color # 实例化类得到对象 cat = MyCat(name="小米", color="yello")

【3】如何查看属性

# 类属性包括数据属性和函数属性 class MyCat(object): # 类的数据属性 home = "小猫比" def __init__(self, name, color): self.name = name self.color = color # 函数属性 def speak(self): print(f'{self.name}正在喵喵叫') cat = MyCat(name="小米", color="yello") print(dir(MyCat)) # 查看类属性,只能包括为初始化对象之前的所有属性 print(dir(myCat))# 查看对象属性,包括实例化得到对象时传入的属性 ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'home', 'speak'] ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'color', 'home', 'name', 'speak']

【4】如何查看名称空间?

class MyCat(object): # 类的数据属性 home = "小猫比" def __init__(self, name, color): self.name = name self.color = color # 函数属性 def speak(self): print(f'{self.name}正在喵喵叫') cat = MyCat(name="小米", color="yello") # 查看名称空间 print(MyCat.__dict__) print(cat.__dict__) # 查看类的属性 print(cat.home) {'__module__': '__main__', 'home': '小猫比', '__init__': <function MyCat.__init__ at 0x000001F9DB8DB7F0>, 'speak': <function MyCat.speak at 0x000001F9DBBC5BD0>, '__dict__': <attribute '__dict__' of 'MyCat' objects>, '__weakref__': <attribute '__weakref__' of 'MyCat' objects>, '__doc__': None} {'name': '小米', 'color': 'yello'} 小猫比 # 对象是基于类来得到的,对象就继承了所有类里面的属性 # 查看类和对象的名称空间发现是一个字典类型,但是又和字典有所区别 # 对象可以 .属性 取值/修改值

【三】绑定方法与非绑定方法

【1】绑定方法:向目标对象(类和对象)绑定的方法

# 绑定给对象的方法:我们正常书写,self自动补全都是对象的绑定方法 class Person(object): def read(self): print("正在读书") # 绑定给类的方法:使用装饰器修饰一下自动补全cls就是类的绑定方法 class Person(object): def read(self): print("正在读书") @classmethod def write(cls): print("正在写书")

【2】非绑定方法:既不给类也不给对象的方法,就是普通方法

# 使用装饰器staticmethod修饰一下,既不给类也不给对象不会自动补全任何参数的方法 class Person(object): def read(self): print("正在读书") @classmethod def write(cls): print("正在写作业") @staticmethod def run(): print("非绑定方法")

【3】调用绑定给对象的方法

class Person(object): def read(self): print("正在读书") @classmethod def write(cls): print("正在写作业") @staticmethod def run(): print("非绑定方法") p = Person() p.read() # 正在读书 类调用绑定给对象的方法 : 第一个参数必须是一个对象 # 在python里面一切皆对象,虽然可以放任意类型,但是为了可扩展性,所以我们选择放实例化得到的对象 Person.read(p)

【4】调用绑定给类的方法

1.# 对象去调用,第一个参数默认检索到创建对象自己的类,将这个类传进去 p = Person() p.write() # 正在写作业 2.# 类调用,哪个类调用的我,就会默认将此类作为第一个参数传入 Person.write() # 正在写作业

【5】非绑定方法

对象和类都可以任意调用,因为就是一个普普通通的函数

Person.run() p = Person() p.run()

【四】面向对象三大特性:封装、继承、多态--->派生、组合

【1】封装

  • 封装就是将某些数据隐藏起来,不被外界所使用,保护隐私

【2】如何修改封装起来的数据?

  • 接口,我们通过开放指定的函数接口,让用户通过指定的接口调用传参数,然后修改属性

【3】如何实现封装?

__变量名

class Person(object): __name = "人类" # __变量名会将我们想要隐藏的属性隐藏起来 # 在第一次实例化类得到对象的时候会对这个变量名做一次变形 # 变形成_Person__name def __init__(self, name, age): self.name = name self.age = age def __speak(self): print(f"{self.name}正在发言!") # 如果想要修改隐藏的属性可以开发一个接口 p = Person(name="lisi", age=18) print(Person.__dict__) print(p) # 实现了对name和speak的封装 {'__module__': '__main__', '_Person__name': '人类', '__init__': <function Person.__init__ at 0x000001C83FD7B7F0>, '_Person__speak': <function Person.__speak at 0x000001C840065BD0>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None} p.__name = 'opp' print(p.__dict__) # 生成新的属性 {'name': 'lisi', 'age': 18, '__name': 'opp'} # 通过接口修改隐藏属性 class Person(object): __name = "人类" def __init__(self, name, age): self.name = name self.age = age def __speak(self): print(f"{self.name}正在发言!") # 如果想要修改隐藏的属性可以开发一个接口 def set_name(self, name): # 在类内部可以任意调用我自己封装起来的和没有封装起来的属性 if not name.isupper(): raise ValueError(f"{name}必须大写") self.name = name # p = Person(name="lisi", age=18) # print(Person.__dict__) # p.__name = 'opp' # print(p.__dict__) # 通过接口修改隐藏属性 p = Person(name="lisi", age=18) p.set_name(name="opp") # 报错: ValueError: opp必须大写 p = Person(name="lisi", age=18) p.set_name(name="OPP") print(p.__dict__) # {'name': 'OPP', 'age': 18}

【4】封装有哪些用处?

  • 封装为了保护我们的隐私数据不被外部发现
  • 封装为了更好的修改和添加
  • 为了更好的模块化开发我们的功能

【五】三大特性之继承

【1】单继承和多继承

  • 父类和子类的概念
  • 父类就是所有子类公共的属性
  • 子类继承了父亲的属性,但是可以延伸出自己的属性和功能(派生)
class Animal(object): def run(self): ... def speak(self): ... # 单继承:一个子类只继承一个父类 class Dog(Animal): def eat(self): ... # 多继承:一个子类可以继承多个父类 class RedDog(Dog,Animal): def set_color(self): ... # 查看子类继承的所有父类 class Animal(object): def run(self): ... def speak(self): ... # 单继承:一个子类只继承一个父类 class Dog(Animal): def eat(self): ... # 多继承:一个子类可以继承多个父类 class RedDog(Dog, Animal): def set_color(self): ... # 查看子类继承的所有父类 __base__:只能看到我子类继承的第一个父类,__bases__可以看到我子类继承的所有父类 print(RedDog.__base__) print(RedDog.__bases__) <class '__main__.Dog'> (<class '__main__.Dog'>, <class '__main__.Animal'>)

【2】深度优先和广度优先

# python2 里面才会分深度优先和广度优先 # 深度优先就是一条道走到黑 # 广度优先就是先走支路。最后走主路 # python3默认都是广度优先 class A: ... class B(A): ... class C(B): ... class D(C): ... class E(C): ... class F(E, D, A): ... # 如果按照深度优先:F--> E -->C -->B -->A -->D # 如果是广度优先 : F -->E -->D --->C --> B ---> A # 记不住,太乱了,分不清,但是还想知道查找顺序 print(F.__mro__) # (<class '__main__.F'>, <class '__main__.E'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)

【3】新式类和经典类

  • python2分经典类和新式类,新式会继承object基类
  • p3不分,都是新式

【4】抽象类

  • 抽象类中定义的函数必须被子类重写或继承,在子类中如果不存在父类中的抽象方法就会报错。
import abc class Animal(object, metaclass=abc.ABCMeta): @abc.abstractmethod def speak(self): ... @abc.abstractmethod def eat(self): ... class Person(Animal): # 必须将Animal里面的两个方法拿进来 def eat(self): ... def speak(self): ... p = Person()

【5】派生

  • 继承父类的所有属性并且衍生出自己的属性
class Animal(object): def __init__(self, animal_name): self.animal_name = animal_name # super超类:将父类的init 方法重新初始化到我当前的类中 # 如果父类中有和子类重名的属性,super在后,得到的属性就是当前父亲中存在的属性 class Dog(Animal): def __init__(self, name, animal_name): super().__init__(animal_name) self.name = name

【6】面向对象之多态

  • 一个事物具有多种形态我们就叫他多态
  • 对于代码来说,子类可以继承父亲衍生出自己的独特的方法就叫多态
class Duck(object): def eat(self): ... def speak(self): ... class RoleDuck(Duck): def eat(self): ... def speak(self): ... class TangDuck(Duck): def eat(self): ... def speak(self): ...

【7】鸭子类型(术语)

# 概念:长得像鸭子,走路也像鸭子,叫起来也像鸭子,那他就是鸭子 # 在这里你就可以把鹦鹉抽象成鸭子

【8】组合

  • 组合其实就是将我们所学到的所有数据类型集合到一起
  • 类可以包容八大基本数据类型
  • 包容函数
class Student(object): def __init__(self, name): self.name = name class Student(object): def __init__(self, name): self.name = name # 放一个类的对象 self.stu = Student(name='zhang') self.class_info = {} self.class_info_class = []

【六】反射

【1】什么是反射

  • 反射是一种程序可以访问、检测和修改其本身状态或行为的能力。

  • 在 Python 中,反射主要指通过字符串的形式操作对象的属性。

  • 通过字符串的形式操作对象相关的属性。

  • python中的一切事物都是对象(都可以使用反射)

【2】反射的方法

  • getattr(object, name[, default])
    • 获取对象的属性值,如果属性不存在,可提供默认值。
  • hasattr(object, name)
    • 判断对象是否具有指定属性
  • setattr(object, name, value)
    • 设置对象的属性值
  • delattr(object, name)
    • 删除对象的属性
class Person(object): def __init__(self, name): self.__name = name # 使用装饰器将 函数属性包装成数据属性 @property def name(self): # 一定要有返回值,并且返回值是字符串 return self.__name # 修改属性 @name.setter def name(self, value): print(value) self.__name = value # 删除属性 @name.deleter def name(self): print(f'删除') p = Person(name='zhang') print(p.name()) print(p.name) p.name = 'opp' del p.name
class Person(object): def __init__(self, name): self.name = name # 绑定给对象的方法 def run(self): print('这是run方法') # 实例化类得到一个具体的对象 p = Person(name='zhang')
【需求】 # 给一个对象,判断一下对象中是否存在该属性 # 如果存在则继续取出来,如果不存在则设置 进去 def check_func(obj=None, key=None, value=None): # 【1】检验属性是否存在 if not hasattr(obj, key): print("不存在该属性") setattr(obj, key, value) print('设置属性完成') else: return getattr(obj, key) p = Person(name='opp') print(check_func(obj=p, key='name')) print(check_func(obj=p, key='gender', value="female")) print(p.gender)

__EOF__

本文作者Fredette
本文链接https://www.cnblogs.com/Fredette/p/17982387.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Fredette  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示