# Day8:类的方法、三大特征、装饰器、组合、多态、设计模式

    技术2024-11-02  55

    文章目录

    方法没有重载私有属性和私有方法@property装饰器面向对象三大特征介绍继承类成员的继承和重写查看类的继承层次结构 object根类重写__ str __()方法多重继承MRO()super()获得父类定义多态特殊方法和运算符重载特殊属性对象的浅拷贝和深拷贝组合设计模式_工厂模式实现设计模式_单例模式实现

    方法没有重载

    class Person: def work(self): print("努力工作") def play_game(s): print("{0}在玩游戏".format(s)) def work2(): print("好好工作,努力上班!赚大钱,娶媳妇!") p = Person() Person.play = play_game p.play() # Person.play(p) 把p的内存地址作为参数传入play_game # <__main__.Person object at 0x0000024BAD2D69B0>在玩游戏 Person.work = work2 p.work() # 由于将work2的内存地址赋值给了Person类中的work,因此在调用p.works是,实际调用的是work2

    私有属性和私有方法

    class Employee: __company = "SXT" def __init__(self, name, age): self.name = name self.__age = age # 私有属性 def __work(self): # 私有方法 print("好好工作,多多赚钱") print("年龄:{0}".format(self.__age)) # 在类的内部可以直接调用私有属性或方法 print(Employee.__company) # 在类的内部可以直接调类的私有属性 e = Employee("彭裤子", 40) # print(e.age) # 报错,无法从外部直接调用私有属性 print(e._Employee__age) print(dir(e)) e._Employee__work() print(Employee._Employee__company)

    @property装饰器

    @property可以将一个方法的调用方式变成“属性调用”,一般用来给属性增加getattr和setattr方法。

    class Employee: @property def salary(slef): return 10000 emp1 = Employee() emp1.salary() print(emp1.salary) # 和属性调用方式一样,但不能赋值,如emp1.salary = 1000 # 一般方法 class Employee: def __init__(self, name, salary): self.__name = name self.__salary = salary def get_salary(self): return self.__salary def set_salary(self, salary): if 1000 < salary < 50000: self.__salary = salary else: print("录入错误,请输入1000-50000的数字") emp1 = Employee("彭裤子", 20000) print(emp1.get_salary()) emp1.set_salary(40000) print(emp1.get_salary()) # 装饰器练习 # 通过get和set方法 class Employee: def __init__(self, name, salary): self.__name = name self.__salary = salary def get_salary(self): return self.__salary def set_salary(self, salary): if 1000 < salary < 50000: self.__salary = salary else: print("录入错误,请输入1000-50000的数字") emp1 = Employee("彭裤子", 20000) print(emp1.get_salary()) emp1.set_salary(40000) print(emp1.get_salary()) # 通过装饰器 class Employee: def __init__(self, name, salary): self.__name = name self.__salary = salary @property def salary(self): return self.__salary @salary.setter def salary(self, salary): if 1000 < salary < 50000: self.__salary = salary else: print("录入错误,请输入1000-50000的数字") emp1 = Employee("彭裤子", 20000) print(emp1.salary) emp1.salary = 2000 # 此处调用的是 @salary.setter print(emp1.salary)

    面向对象三大特征介绍

    继承

    继承是面向对象程序设计的重要特征,也是实现“代码复用”的重要手段。如果一个新类继承自一个设计好的类,就直接具备了已有类的特征,这就大大降低了工作难度。已有的类,我们称为“父类或者基类”,新的类,我们称为“子类或者派生类”。

    子类可以继承父类的私有方法和属性,但不能直接调用; # 继承 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, score): Person.__init__(self, name, age) self.score = score print(Student.mro()) # [<class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>] s = Student("彭裤子", 40, 100) s.say_age() # 继承了父类的方法 print(dir(s)) """ ['_Person__age', '__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__', 'name', 'say_age', 'score'] """ print(s._Person__age)

    类成员的继承和重写

    成员继承:子类继承了父类除构造方法之外的所有成员方法重写:子类可以重新定义父类中的方法,这样就会在调用子类的相同的方法时覆盖父类的方法,也称为“重写”,其他子类依然继承父类中未被改变的方法

    查看类的继承层次结构

    通过类的方法mro()或者类的属性__ mro __可以输出这个类的继承层次结构。

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

    object根类

    class Person: def __init__(self, name, age): self.name = name self.__age = age p = Person("彭裤子", 40) print(dir(object)) ''' ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__'] ''' print(dir(p)) ''' ['_Person__age', '__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__', 'name'] '''

    Person对象增加了几个属性:

    ['_Person__age', '__dict__', '__weakref__', 'name']

    object的所有属性,Person类作为object的子类,显然包含了所有的属性

    重写__ str __()方法

    object有一个__ str __()方法,用于返回一个对于“对象的描述”。对应与内置函数str(),经常用于print()方法,帮助我们查看对象的信息,该方法可以重写。

    # __str__()重写前 class Person1: def __init__(self, name): self.name = name p = Person1("彭裤子") print(p) # 返回一个对于“对象的描述”<__main__.Person object at 0x0000022E03906780> # 重写__str__() class Person2: def __init__(self, name): self.name = name def __str__(self): return "名字是:{0}".format(self.name) p = Person2("彭裤子") print(p) # 名字是:彭裤子

    多重继承

    python支持多重继承,一个子类可以有多个“直接父类”。这样,就具备了“多个父类”的特点。但是由于,这样会被“类的整体层次”搞得异常复杂,尽量避免使用。

    MRO()

    Python支持多继承,如果父类中有相同名字的方法,在子类没有指定父类名时,解释器将“从左向右”按顺序搜索。

    如class C(A,B,C) 则搜索顺寻为A–B--C

    MRO(Method Resolution Order):方法解析顺序。我们可以通过mro()方法获得“类的层次结构”,方法解析顺序也是按照这个“类的层次结构”寻找的。 class A: def aa(self): print("aa") def say(self): print("sayAAA!") class B: def bb(self): print("bb") def say(self): print("sayBBB!") class C(B, A): def cc(self): print("cc") c = C() print(C.mro()) # 打印类的层次结构 c.say() # 解释器寻找方法时"从左到右"的方式寻找,此是会执行B类

    super()获得父类定义

    在子类中,如果想要获得父类的方法时,我们可以通过super()来做。

    super()代表父类的定义,不是父类对象。

    class A: def say(self): print("A:", self) class B(A): def say(self): # A.say(self) super().say() print("B:", self) b = B() b.say()

    多态

    class Man: def eat(self): print("饿了,吃饭啦") class Chinese(Man): def eat(self): print("中国人用筷子吃饭") class English(Man): def eat(self): print("英国人用叉子吃吃饭") class Indian(Man): def eat(self): print("印度人用右手吃饭") def man_eat(m): if isinstance(m, Man): m.eat() # 多态,一个方法调用,根据对象不同,调用不同的方法 else: print("不能吃饭") man_eat(Chinese()) # 中国人用筷子吃饭 man_eat(English()) # 英国人用叉子吃吃饭 man_eat(Man()) # 饿了,吃饭啦

    特殊方法和运算符重载

    # 重构__add__方法,实现同类型对象才能相加的功能 class Person: def __init__(self, name): self.name = name def __add__(self, other): if isinstance(other, Person): return "{0}--{1}".format(self.name, other.name) else: return "不是同类对象,不能相加" def __mul__(self, other): if isinstance(other, int): return self.name * other else: return "不是同类对象,不能相乘" class Dog: pass p1 = Person("彭裤子") p2 = Person("不堵车的蒋老斯") p3 = Dog() x = p1 + p2 print(x) y = p2 + p3 print(y) print(x * 30)

    特殊属性

    class A: pass class B: pass class Metal(B, A): def __init__(self, name): self.name = name def say_yeah(self): print("燥起来") c = Metal("Megadeth") print(dir(c)) # 获得c的所有属性 print(c.__dict__) # {'name': 'Megadeth'} print(c.__class__) # 查看对象c属于哪个类 print(Metal.__bases__) # 查看Metal类的继承顺序 print(Metal.mro()) # 查看类的层次结构 print(A.__subclasses__()) # 查看父类的子类

    对象的浅拷贝和深拷贝

    import copy class MobilePhone: def __init__(self, cpu, screen): self.cpu = cpu self.screen = screen class CPU: def calculate(self): print("算你个12345") print("cpu对象:", self) class Screen: def show(self): print("显示一个好看的画面,亮瞎你的钛合金眼") print("screen对象:", self) # 测试变量赋值 c1 = CPU() c2 = c1 print(c1) print(c2) # 测试浅复制 print("浅复制") s1 = Screen() m1 = MobilePhone(c1, s1) m2 = copy.copy(m1) print(m1, m1.cpu, m1.screen) print(m2, m2.cpu, m2.screen) # 测试深复制 print("深复制") m3 = copy.deepcopy(m1) print(m1, m1.cpu, m1.screen) print(m3, m3.cpu, m3.screen)

    组合

    # 使用继承实现代码的复用 class A1: def say_a1(self): print("a1,a1,a1") class B1(A1): pass b1 = B1() b1.say_a1() # 同样的效果,使用组合实现代码的复用 class A2: def say_a2(self): print("a2,a2,a2") class B2(A2): def __init__(self, a): self.a = a a2 = A2() b2 = B2(a2) b2.a.say_a2() # 相当于实现了a2.say_a2(),B2(a2)实例化时,传递的是a2内存地址,b2.a相当于a2 # 例1 class MobilePhone: def __init__(self, cpu, screen): self.cpu = cpu self.screen = screen class CPU: def calculate(self): print("算你个12345") print("cpu对象:", self) class Screen: def show(self): print("显示一个好看的画面,亮瞎你的钛合金眼") print("screen对象:", self) m = MobilePhone(CPU(), Screen()) m.cpu.calculate() m.screen.show()

    设计模式_工厂模式实现

    # 测试工厂模式 class CarFactory: def create_car(self, brand): if brand == "奔驰": return Benz() elif brand == "宝马": return BMW() elif brand == "比亚迪": return BYD() else: return "位置品牌,无法创建" class Benz: pass class BMW: pass class BYD: pass factory = CarFactory() c1 = factory.create_car("奔驰") c2 = factory.create_car("比亚迪") print(c1) print(c2)

    设计模式_单例模式实现

    class MySingleton: __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 MySingleton.__init_flag: print("init......") self.name = name MySingleton.__init_flag = False a = MySingleton("aa") b = MySingleton("bb") print(a) print(b) c = MySingleton("cc") print(c.name) print(a.name)
    Processed: 0.020, SQL: 9