第19天 一切皆对象 装饰器:property setter delete classmethod staticmethod 绑定方法与非绑定方法 继承基础知识 先抽象再继承

类与对象内置的一些装饰器及功能

property:通常配合隐藏属性一起使用

classmethod:绑定给类的方法,绑定给类的,无论谁来调用都会自动传入类

staticmethod:没有跟任何类和对象进行绑定,谁来调用都是一个普通函数

一切皆对象代码原理

class Student:
    n = 0

    def __init__(self, name, age, gender):
        Student.n += 1
        self.name = name
        self.age = age
        self.gender = gender

    def choose(self):  # self = obj1
        print("hello %s" % self.name)


obj1 = Student("nana", 18, "female")
print(type(obj1))
print(Student)
print(obj1.__dict__)
obj1.choose()      #对象调函数传参
Student.choose(obj1)     #类调函数传参

内置类=内置类型
print(list)
l1 = list([1, 2, 3])
print(type(l1))
print(l1)
l1.append(4)  #[1, 2, 3, 4]
list.append(l1, 4)  # [1, 2, 3, 4]

装饰器:property
property:通常配合隐藏属性一起使用,被property装饰过的函数可以将功能属性的函数直接伪装成数据属性的函数

class People:
    def __init__(self, name, weight, height):
        self.name = name
        self.weight = weight
        self.height = height

    @property   #被property装饰过的函数可以不用再加()运行,直接将bmi伪装成数据属性的函数
    def bmi(self):
        return self.weight / (self.height ** 2)


p1 = People("dada", 75, 1.8)

print(p1.bmi)

同一个属性没有增加,可以删改查

class People:
    def __init__(self, name):
        self.__name = name

    @property
    def name(self):
        return self.__name

    @name.setter  # 函数名.setter装饰过的函数,可以直接修改形参x.可以直接写成p1.name="lala")
    def name(self, x):
        if type(x) is not str:
            raise Exception("名字必须是字符串类型")  # raise Exception主动抛出异常
        self.__name = x

    @name.deleter
    def name(self):
        print("不允许删除")


p1 = People("nana")
print(p1.name)  # 调用查看名字的接口

p1.name = "lala"  # 调用修改名字的接口
print(p1.name)

del p1.name  # 调用删除接口
print(p1.name)


写法二:
class People:
    def __init__(self, name):
        self.__name = name

    def get_name(self):
        return self.__name

    def set_name(self, x):
        if type(x) is not str:
            raise Exception("名字必须是字符串类型")  # raise Exception主动抛出异常
        self.__name = x

    def del_name(self):
        print("不允许删除")

    name = property(get_name, set_name, del_name)


p1 = People("nana")  # 调用查看名字的接口
print(p1.name)

p1.name = "lala"  # 调用修改名字的接口
print(p1.name)

del p1.name  # 调用删除接口

绑定方法与非绑定方法
绑定方法
特点:绑定给谁就应该由谁来调用,谁来调用就会将自己当作第一个参数传入

非绑定方法
特点:不与类和对象绑定,意味着谁都可以来调用,但无论谁来调用就是一个普通函数,没有自动传参的效果

class People:
    def __init__(self, name):
        self.name = name

    # 但凡在类中定义一个函数,默认就是绑定给对象的,应该由对象来调用,
    # 会将对象当作第一个参数自动传入
    def tell(self):
        print(self.name)


    # 类中定义的函数被classmethod装饰过,就绑定给类,应该由类来调用
    # 类调用会将类本身当作第一个参数自动传入
    @classmethod  # classmethod会将函数f1绑定给类People
    def f1(cls):  # cls=People
        print(cls)

    # 类中定义的函数被staticmethod装饰过,就成了一个非绑定的方法即一个普通函数,谁都可以调用
    # 但无论谁来调用就是一个普通函数,没有自动传参的效果
    @staticmethod  # staticmethod会将函数f2变成非绑定方法的普通函数
    def f2(x, y):
        print(x, y)

p1 = People("nana")
p1.tell()

print(People.f1)  # 打印结果显示为一个绑定方法<bound method People.f1 of <class '__main__.People'>>
People.f1()

People.f2(1, 2)
p1.f2(3, 4)

装饰器的案例使用场景

import setting



class People:
    def __init__(self, name, age, gender):
        self.id = self.creat_id()
        self.name = name
        self.age = age
        self.gender = gender

    def tell_info(self):
        print(self.name, self.age, self.gender)

    @classmethod  # 绑定给类的方法应该由类去调用,如果对象去调用还是会自动传入类的参数
    def from_conf(cls):  # 导入模块setting,从配置文件读取文件完成实例化
        return cls(setting.name, setting.age, setting.gender)

    @staticmethod  # 非绑定方法
    def creat_id():
        import uuid
        return uuid.uuid1()


p1 = People("lala", 18, "male")

p2 = People.from_conf()
print(p2.__dict__)

print(p1.creat_id())
print(People.creat_id())

print(p1.__dict__)

继承
继承是创建新类的一种方式
新建的类称为子类
被继承的类称为父类,基类,超类
继承的特点是:子类可以遗传父类的属性

类是用来解决对象之间冗余问题的
而继承则是来解决类与类之间冗余问题的
继承具有耦合的特性,与面向对象扩展性的强的特性是相悖的,用继承需要慎用

新式类与经典类
但凡是继承了object类的子类以及该子类的子子孙孙类都是新式类
反之就是经典类

在python2中有新式类与经典类之分,在python3中默认全是新式类
如果在python2中把经典类改成新式类,需要在类名称的后面加(object)


在python中支持多继承
class Parent1:
    pass


class Parent2:
    pass


class Sub1(Parent1):
    pass


class Sub2(Parent1, Parent2):
    pass


print(Sub1.__bases__)  # (<class '__main__.Parent1'>,)
print(Sub2.__bases__)  # (<class '__main__.Parent1'>, <class '__main__.Parent2'>)

print(Parent1.__bases__)  # (<class 'object'>,)
print(Parent2.__bases__)  # (<class 'object'>,)

先抽象,再继承

继承描述的是子类与父类之间的关系,是一种什么是什么的关系。要找出这种关系,必须先抽象再继承
抽象即抽取类似或者说比较像的部分。

抽象分成两个层次:

1.将奥巴马和梅西这俩对象比较像的部分抽取成类;

2.将人,猪,狗这三个类比较像的部分抽取成父类。

抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)

在这里插入图片描述
继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构
抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类
在这里插入图片描述

继承背景下的属性查找
继承背景下的属性查找的顺序:先从对象里面找,如果对象里面没有,再从类里面查找,如果类里面也没有,再从父类里面找

class Bar:  # Bar的父类不写默认是object
    y = 666


class Foo(Bar):
    def __init__(self, x):
        self.x = x


obj = Foo(111)
print(obj.__dict__)
print(obj.x)
print(obj.y)
示例一:
class Bar:
    def f1(self):
        print("Bar.f1")

    def f2(self):
        print("Bar.f2")
        self.f1()  # obj.f1()


class Foo(Bar):
    def f1(self):
        print("Foo.f1")


obj = Foo()  # Foo.f1
obj.f2()  # Bar.f2


示例二:
class Bar:
    def __f1(self):  # _Bar__f1
        print("Bar.f1")

    def f2(self):
        print("Bar.f2")
        self.__f1()  # _Bar__f1


class Foo(Bar):
    def __f1(self):  # _Foo__f1
        print("Foo.f1")


obj = Foo()  # Bar.f1
obj.f2()  # Bar.f2

猜你喜欢

转载自blog.csdn.net/Yosigo_/article/details/112489406