当前位置: 移动技术网 > IT编程>脚本编程>Python > # Day8:类的方法、三大特征、装饰器、组合、多态、设计模式

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

2020年07月05日  | 移动技术网IT编程  | 我要评论

方法没有重载

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-piKNnao1-1593788847368)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200702203543804.png)]

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

私有属性和私有方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8SMKqohD-1593788847372)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200702203251806.png)]

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)

面向对象三大特征介绍

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uxJE1a8F-1593788847374)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200702213324102.png)]

继承

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kC4Mg1JW-1593788847377)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200702221412299.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, 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根类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dUoMjeU5-1593788847378)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200703093952254.png)]

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PzXBFxgc-1593788847380)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200703101059587.png)]

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()

多态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hJ7fqJIn-1593788847381)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200703163026809.png)]

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)

特殊属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5CHguQzZ-1593788847382)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200703213717084.png)]

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__())  # 查看父类的子类

对象的浅拷贝和深拷贝

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bSVn59gI-1593788847383)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200703214041178.png)]

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)

组合

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GHzBn7Iz-1593788847384)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200703215646549.png)]

# 使用继承实现代码的复用
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()

设计模式_工厂模式实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fl4XZ0M0-1593788847384)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200703222957977.png)]

# 测试工厂模式
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)

设计模式_单例模式实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xFNxjPqx-1593788847385)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200703224044028.png)]

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)

本文地址:https://blog.csdn.net/spike1988zc/article/details/107117234

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网