绑定方法与非绑定方法、隐藏属性、property装饰器、面向对象的三大特征

发布时间 2023-06-26 21:16:24作者: Maverick-Lucky

绑定方法

绑定给对象的方法

特殊之处:函数的第一个形参self就是对象自己。

绑定给对象的方法就会有对象来调用,会把对象自己当成第一个参数传给第一个形参self

类调用,就需要传参数,方法里面有几个参数就要传几个参数

class Student():
    school = 'SH'  # 类的属性
    
    def __init__(self, name, age, gender):
        self.name = name  # self:对象自己
        self.age = age
        self.gender = gender


    # 绑定给对象的方法
    def tell_info(self):  # self:也是对象自己
         print("name:%s, age:%s, gender:%s" % (self.name, self.age, self.gender))


stu = Student('kevin', 18, 'male')  # 调用类产生一个对象
stu.tell_info()  # stu.tell_info(stu)  # name:kevin, age:18, gender:male

绑定给类的方法

绑定给类的方法就由类来调用,特殊之处就是:会把类名当成第一个参数传递给方法的第一个形参。

# 绑定给类的方法
# ip:127.0.0.1 port:3306 ====> ip+port可以唯一确定一台计算机上的一款软件
import settings


class Mysql():
    def __init__(self,ip,port):
        self.ip = ip
        self.port = port

    @classmethod  # 加了classmethod装饰器,该方法就变成了绑定给类的方法
    def from_func(cls): # self 就可以写成cls, cls就是类名
        print('123')
        return cls(settings.ip,settings.port)


obj = Mysql(settings.ip,settings.port)
res = Mysql.from_func()

非绑定方法

非绑定方法就是:不绑定给类使用,也不绑定给对象使用

又叫:静态绑定(关键字:static)

补充:uuid ,只要了解 uuid4,只要随机串的长度一定,理论上,一定会出现重复的可能性。

import uuid
print(uuid.uuid4())  # d2cf6751-cc90-4238-90dd-8ebfacd6140c

订单号的不重复:uuid+时间戳。

@staticmethod 装饰器该方法已经谁都不绑定,类和对象都可以直接来调用

class Student():
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
        self.id = self.create_id()

    """什么时候使用静态方法:一般就是方法里面既不用对象,也不用类的时候就使用静态方法"""
    @staticmethod  # 该方法已经谁都不绑定,谁都能来调用。
    def create_id():
        import uuid
        return uuid.uuid4()
stu = Student('hua',18,'male')
print(stu.id) # 打印随机串
l =str(stu.id)[:13] # 切分随机串
print(l.replace('-','')) # 将-去掉

隐藏属性

在属性名前加__前缀,就会实现一个对外隐藏属性的效果。

class Student():
    country = 'China'

    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def __func(self):
        print('from func')


obj = Student('hua', 18)
print(obj.__dict__) # AttributeError: 'Student' object has no attribute 'name'
print(obj.name, obj.age)  # hua 18

这种隐藏对外不对内,因为__开头的属性会在类定义时发生统一发生变形:_类名__属性名:

这种变形操作只在类定义的时候发生一次,之后的定义的__开头的属性都不会变形

为什么要隐藏?

因为隐藏属性是对外部对内的,当想在外部使用时,需要在类的内部开放一个接口,返回隐藏属性的值,以便更好的对外做限制。

class Student():
    __country = 'China'
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __func(self):  # _Student__func  _类名__函数名
        print('from func')
    def index(self):
        return self.__country  # self._Student__school

obj = Student('hua', 18)
print(obj.__dict__)  # {'_Student__name': 'hua', '_Student__age': 18}
print(obj.name, obj.age)  # hua 18
obj._Student__func()  # from func
print(obj.index())  # China

property装饰器

作用:就是把方法伪装成属性来使用

class Student():
    __country = 'China'
    __city = 'shanghai'

    def __init__(self, name, age, gender):
        self.__name = name  # _Student__name
        self.age = age
        self.gender = gender

    @property
    def country(self):
        return self.__country

    @country.setter
    def country(self, v):
        if type(v) is not str:
            return
        Student.__country = v

    @country.deleter
    def country(self):
        print("可以删除了")
        del Student.__country

    @property
    def city(self):
        return self.__city

    @city.setter
    def city(self, v):
        Student.__city = v

    @city.deleter
    def city(self):
        print("可以删除了")
        del Student.__city

stu = Student("kevin", 20, 'female')
print(stu.country)
stu.country = 'Japan'
print(stu.country)

del Student.country
stu.country('Japan')
del stu.country
# 方式2

class Student():
    __country = 'China'
    __city = 'SH'

    def __init__(self,name,age,gender):
        self.name =name
        self.age = age
        self.gender = gender
    def get_country(self):
        return self.__country
    def set_country(self,v):
        if type(v) is not str:
            return
        Student.__country = v
    def del_country(self):
        print('删除')
        del Student.__country
    # 这种方法是有顺序要求的
    country = property(get_country,set_country,del_country)
stu = Student('hua',18,'male')
print(stu.country) # China
stu.country = 'Japan'
print(stu.country) #Japan
del stu.country # 删除

课堂练习

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

    @property
    def bmi(self):
        return self.weight / (self.height ** 2)

bmi = Bmi(50, 1.55)
print(bmi.bmi) # 20.811654526534856

面向对象的三大特征

封装:是一种思想,将冗余的代码,重复的代码都封装成函数,以后每次都调用函数来用

继承:是新建类的一种方式,新建出来的类称为是子类或者叫派生类,被继承的类称为是父类或者叫基类。

多态

子类可以继承基类的所有属性和方法

类解决的问题:对象与对象之间的代码冗余问题

 继承解的问题:类与类之间的代码冗余问题

继承方式:

新式类:继承了object类的子子孙孙类都是新式类
经典类:没有继承object类的子子孙孙类都是经典类

# 以学生选课系统为例
class People():
    school = 'SH' # 严格依赖继承
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

class Student(People):
    def __init__(self, name, age, gender, course):
        """这个是指名道姓的调用方法,不依赖于继承"""
        People.__init__(self, name, age, gender) # 有什么特殊之处,
        self.course = course

    def choose_course(self):
        pass

stu = Student('kevin', '19', 'male', 'python')

# 对象属性的查找顺序:先从对象自己的名称空间查找,如果找不到,再去类中取查找,如果找不到,取继承的父类转中查找,
print(stu.school)
print(stu.name)
class Teacher(People):
    def __init__(self,name, age, gender, level):
        People.__init__(self, name, age, gender)  # 有什么特殊之处,
        self.level = level

    def score(self):
        pass

tea = Teacher("ly", 20, 'female', 10)
print(tea.school)