Python 对象学习篇

记录于 10.6
观前提醒,涉及大量图片,以及大量生涩难记的概念,请参考原文:Python 学习日记 - 10.6

面向对象与面向过程区别

Python支持面向过程、面向对象、函数式编程

Python中一切皆对象

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/d305a715-ece5-40d3-8ff7-0a15ca0e4d04/Untitled.png

面向过程到面向对象,编程思维的转变

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/fd04e0e0-ed47-4cef-8a91-1b97aa794488/Untitled.png

类的定义-类和对象的关系

  • 对象就像是一个物品
  • 类就是制造这个物品的模具

但一切都是对象,因此类本身也是对象

  • 类的本质是将行为和状态打包在一起

类的定义:


class Student:

    def __init__(self,name,score): # self必须在第一个参数位
        self.name = name
        self.score = score

    def say_score(self): # self必须在第一个参数位
        print(f"{self.name}的分数是{self.score}?")

s1 = Student("谁",18)
s1.say_score()
s1.age = 32
s1.salary = 35200
print(f"{s1.name}的工资是:{s1.salary},也不大才{s1.age},分数才{s1.score},不知道走了什么狗屎运!")

out:
谁的分数是18?
谁的工资是:35200,也不大才32,分数才18,不知道走了什么狗屎运!
  • 需要注意的是,在init左右两边各有两条下划线,否则会报错。

构造函数 **init**()

在调用类定义对象时,先执行了__new__()方法创建对象,再执行构造函数__init__()初始化对象。

  • 要点为:名称固定,第一个参数必须为self,在类里定义的函数都必须加上self
  • 实例属性往往是名称与形参一样
  • Python中的 self 相当于C++中的 Self 指针,Java和 C# 中的 this 关键字

实例属性

  • 实例属性一般在 构造函数 中定义
  • 可以用 对象.实例属性 的方法调用
  • self 不需要传参,解释器自己会传参
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/b9fe1103-5078-4f35-9097-1fe5e2b8ec8e/Untitled.png
  • dir(Obj) 可以获得对象所有的属性和方法
  • pass 空语句
  • isinstance(Obj, Class) 判断对象是否属于该类
  • 类对象的类型就是 Class type

类属性

  • 类属性属于类,可以被所有实例对象共享
  • 在这里类属性 count 被调用了几次取决于初始化过几次
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/3f7544a2-7b63-423c-b9b4-10daf1a52b06/Untitled.png
  • 栈堆图详解
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/ec2a90f7-378e-4ebd-b55a-878f5bcc9bbe/Untitled.png
  • 实例对象中只存储实例属性、以及方法的引用地址,类属性与方法的对象都存在类里

类方法

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/aa23ccd6-424e-43d0-bbde-1deaea90ae80/Untitled.png
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/2d50791c-c4a3-49d2-bce2-0327292fa3e2/Untitled.png
  • 类方法与实例函数的区别在于,该方法可以被所有实例对象共同调取,也可以被类本身直接调取;

静态方法

与类完全无关的方法,放在类里的函数

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/a9e59bd2-833b-4a30-b50a-6571cab8ecf6/Untitled.png

__del__析构函数和垃圾回收机制

上述析构方法,用于实现对象被销毁时所需要的操作,

  • 释放对象占用的资源
  • python实现自动的垃圾回收,当对象没有被引用时(引用计数为0),由垃圾回收器调用析构函数;
  • del 方法本质上是调用析构函数

__call__方法和可调用对象

  • 定义了 call 方法的对象,称为可调用对象,即该对象可以像函数一样被调用。
  • 最好带返回值
  • 可以直接使用 Obj() 的形式调用
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/fccf850a-b49c-412d-96c4-c5bda7fea8b1/Untitled.png

Python中没有方法重载

重载也不是个好东西啊,容易导致效率低下

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/0809ada3-0d17-4ff7-92e6-fab851098625/Untitled.png

私有属性和私有方法

  • 需要用 “下划线 类名 下划线 下划线 私有属性” 或者 “下划线 类名 下划线 下划线 私有方法” 调用
  • 私有方法在定义的时候,前面加俩下划线
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f97072ee-b797-4d21-ae66-f23192adea2c/Untitled.png

@property 装饰器

将一个方法转为属性调用

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/cd94a4b8-e351-4f50-8a73-6474de8444f8/Untitled.png

例1:

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/cd47fbcd-e5b3-4f91-88e1-799d57891ddb/Untitled.png

例2:

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/e5343a2b-9c51-4348-b977-abaa07b8cff7/Untitled.png
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/9f3dc21d-083d-4c75-b87b-eb59c4f6a608/Untitled.png

面向对象的三大特征

  • 封装
  • 继承
  • 多态

封装

  • 隐藏对象的细节,对外只提供必要的方法,将细节封装起来,只对外暴露“相关调用方法”

继承

  • 继承可以让子类具有父类的特征,提高代码的重用性
  • 设计上是一种增量进化,原有父类设计不变的情况下,可以增加新的功能,或改进已有的算法

代码复用的重要手段

  • 定义的时候,在小括号里加上父类,可以多重继承
  • 继承了父类的所有属性,但不能直接用父类的私有属性
  • 如果没有指定父类,那么所有的类的父类都是Object
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/6e8ec0e3-be41-4360-b532-89dc9ee08a40/Untitled.png
  • 子类初始化范例,通过调用父类的方法进行初始化
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/cb5de638-1ae8-4537-b517-8872c943961b/Untitled.png

父类方法的继承与重写

父类的重写比较常见


class Person():
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def say_age(self):
        print("我就是个无情的测试语句")

class Student(Person):
    def __init__(self,name,age):
        Person.__init__(self,name,age)

    def say_age(self):
        print("shwta")

s1 = Student("Qiu mouren",22)
s1.say_age()
s2 = Person("WoJiuShuo",300)
s2.say_age()

>>>python c:/Users/ZekShawn/Desktop/test.py
shwta
我就是个无情的测试语句

Object 根类

所有的自定义类包含了Object根类的属性

  • 类的方法也是属性,只不过方法的类型为method

class A:pass
class B(A):pass
class C(B,A):pass
print(C.mro())

>>>python c:/Users/ZekShawn/Desktop/test.py
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

重写 str 方法


class Person():     # 默认继承根类
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def say_age(self):
        print("我就是个无情的测试语句")

    def __str__(self):
        print("测试是否被重写")
        return f"Name is {self.name}, and no other message!"

p = Person("swd",22)
print(p)

>>>python c:/Users/ZekShawn/Desktop/test.py
测试是否被重写
Name is swd, and no other message!

多重继承

自左往右,如果子类里没有该方法,又被调用时

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/0407a8f2-cd57-4440-a435-df23d0f1212f/Untitled.png

获得父类定义,直接调用父类方法

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/83c6995e-7bd6-4e42-b21a-eed92b509c9b/Untitled.png

多态

  • 指同一个方法调用由于对象不同产生不同的行为
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/4ae0ffe8-c65c-4a71-b823-f33b1dd25539/Untitled.png
  • 运算符可以重载
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/1ad67013-48ee-4ba7-8f39-862274c0df9c/Untitled.png

重载 + 运算

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/5d2319ef-6d9f-4016-9d1e-d072b4343567/Untitled.png
  • 常用函数也可以重载
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/eb907c82-6903-4885-85c5-5bdc319bbce2/Untitled.png

特殊属性

对于Python中的对象,有一些特殊的属性

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/d2f6853b-f3ae-4c99-93ba-879456e99ba2/Untitled.png

示例如下:


class Person():     # 默认继承根类
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def say_age(self):
        print("我就是个无情的测试语句")

    def __str__(self):
        print("测试是否被重写")
        return f"Name is {self.name}, and no other message!"

class Student(Person):

    def __init__(self,name,age):
        Person.__init__(self,name,age)

    def say_age(self):
        super().say_age()
    pass

p = Student("swd",22)
p.say_age()
print(p.__dict__)

>>>python c:/Users/ZekShawn/Desktop/test.py
我就是个无情的测试语句
{'name': 'swd', 'age': 22}

测试如下:

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/b09d3e51-e3b3-4171-a9ae-8a355525ec25/Untitled.png

组合

  • 组合也可以实现一个类拥有另一个类的方法和属性
  • 面向对象可以帮助更好的构建程序的实现逻辑

有时候两者之间存在联系,却不能直接继承,比如下例中的手机与CPU

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/6f66ce9d-9aba-4fe2-a094-633332be36e7/Untitled.png
  • 如下图所示,可以将一个对象传入另一个对象的属性
  • 接着从其中一个对象属性调用另一个对象的方法
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/7770b4c1-ad3e-47c2-91b5-14b16dfd1949/Untitled.png

设计模式-工厂模式

  • GOF23种设计模式
  • 工厂模式主要实现了创建者和调用者的分离
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/fc807936-b0ed-4884-b450-ed848df46ae5/Untitled.png

# 测试工厂模式
# GOF(Group Of Four)23

class CarFactory:
    def createCar(self,brand):
        if brand == "Benci":
            return Benci()
        elif brand == "BMD":
            return BMD()
        elif brand == "BYD":
            return BYD()
        else:
            return "Sorry, there's no this kind of brand!"

class Benci:
    pass

class BMD:
    pass

class BYD:
    pass

factory = CarFactory()

c1 = factory.createCar("Benci")
c2 = factory.createCar("BYD")

print(c1,c2)

>>>python c:/Users/ZekShawn/Desktop/test.py
<__main__.Benci object at 0x000001E6693BA280> 
<__main__.BYD object at 0x000001E6693C3430>

设计模式-单例模式

核心就是确保一个类只有一个实例,并且提供一个访问该实例的全局访问点。

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/aa05e1d0-b4a3-4e95-8a06-c9e1e555dcea/Untitled.png

单例模式


# 测试单例模式
# GOF(Group Of Four)23

class mySimple:
    __obj = None        # 类属性
    __init_flag = True

    def __new__(cls, *args, **kwargs):
        if cls.__obj == None:
            cls.__obj = object.__new__(cls)
        
        return cls.__obj
    
    def __init__(self,name):
        if mySimple.__init_flag:
            self.name = name
            mySimple.__init_flag = False
            
a = mySimple("sw")
b = mySimple("wd")
print(a.name)
print(b.name)
print(a)
print(b)

>>>python c:/Users/ZekShawn/Desktop/test.py
sw
sw
<__main__.mySimple object at 0x0000027D2C4B3610>
<__main__.mySimple object at 0x0000027D2C4B3610>

工厂模式的工厂对象转化为单例模式


# 测试工厂模式
# GOF(Group Of Four)23

class CarFactory:

    __obj = None
    __init_flag = True

    def createCar(self,brand):
        if brand == "Benci":
            return Benci()
        elif brand == "BMD":
            return BMD()
        elif brand == "BYD":
            return BYD()
        else:
            return "Sorry, there's no this kind of brand!"

    def __new__(cls):
        if cls.__obj == None:
            cls.__obj = object.__new__(cls)
        return cls.__obj

    def __init__(self):
        if CarFactory.__init_flag:
            CarFactory.__init_flag = False

class Benci:
    pass

class BMD:
    pass

class BYD:
    pass

factory1 = CarFactory()
factory2 = CarFactory()

c1 = factory1.createCar("Benci")
c2 = factory2.createCar("BYD")

print(c1,c2)
print(factory1,factory2)

>>>python c:/Users/ZekShawn/Desktop/test.py
<__main__.Benci object at 0x0000027F74493580> 
<__main__.BYD object at 0x0000027F744931F0>     
<__main__.CarFactory object at 0x0000027F74493610> 
<__main__.CarFactory object at 0x0000027F74493610>

太棒啦,如果你看了我前面的文章,那么恭喜你,学完Python的入门知识了,加油吧少年。

  • 总觉得上面的这段话好中二啊,哈哈哈哈,不过学完了确实很舒服。头疼,走了不少弯路,估计过段时间整理一下我的学习历程分享给电脑这端的你。
赞赏