面向对象进阶

1. 绑定方法和非绑定方法

绑定方法 对象绑定方法/类的绑定方法

绑定方法:特殊之处,绑定给谁就是谁来调,并且会把自身传过来

类的绑定方法:绑定给类的,类来调用,会把类自身传过来

类的绑定方法用在什么地方:不需要通过对象,只需要通过类就能获取到一些东西的时候

类的绑定方法可以用对象来调

class Person:
    def __init__(self,name,age):
        print(self)
        self.name = name
        self.age = age
    @classmethod
    def test(cls):
        print(cls)
        print('类的绑定方法')
        # 类实例化产生对象,返回
        return cls('lqz',19)

Person.test()

Person('nick',18)

class Admin:
    def __init__(self,name,age):
        print(self)
        self.name = name
        self.age = age
    @classmethod
    # 类的绑定方法
    def get_obj_by_name(cls,name):
        # 取到类的名字
        type_class = cls.__name__.lower()
        # 1 去文件中查找名字为name的pickle文件
        # 2 序列化成对象
        # 3 return 对象
        pass
    # 对象的绑定方法
    def get_obj_by_name1(self,name):
        # 1 去文件中查找名字为name的pickle文件
        # 2 序列化成对象
        # 3 return 对象
        pass

# 类
admin = Admin.get_obj_by_name('lqz')

admin = Admin.get_obj_by_name1(None,'lqz')
# 对象
admin = Admin('nick',19)
admin1 = admin.get_obj_by_name('lqz')


# 类的绑定方法可以用对象来调
class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    @classmethod
    def test(cls):
        print(cls)
        print('类的绑定方法')

# Person.test()
p = Person('nick',18)
# 对象可以调用类的绑定方法,也是把该对象的类传入
p.test()

'''
总结:
    classmethod 是个装饰器,放在类中的函数上面,该函数就变成了类的绑定方法
    类的绑定方法由类来调用,自动把类传过去(对象也可以调,一般不用)
    类的绑定方法用在什么地方?
    不需要通过对象,只需要通过类就能完成某些事的时候,就把该方法定义为类的绑定方法
'''

2. staticmethod 非绑定方法

staticmethod 非绑定方法,定义在类内部,普通方法,谁都不绑定

对象/类都可以调用,但是不会自动传值

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

    def object_method(self):
        print('我是对象绑定方法,对象来调用我')

    @classmethod
    def class_method(cls):
        print('我是类的绑定方法,类来调用我')

    # 当成一个普通函数,只不过是写在类内部的
    @staticmethod
    def static_method():
        print('我是静态方法,谁都不绑定')

# 静态方法(非绑定方法)
# 类来调用
Person.static_method()
# 对象来调用
p = Person('nick',19)
p.static_method()

'''
# 生成一个唯一的id号
import uuid
print(uuid.uuid4())
'''

# 静态方法(非绑定方法)的作用
# 跟类和对象都没有关系的时候,可以定义成静态方法,一般在类内部使用,类外部也可以使用
# 就是一个普通函数,想把它拿到类中管理,就可以定义成静态方法

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

    # 当成一个普通函数,只不过是写在类内部的
    @staticmethod
    def static_method():
        print('我是静态方法,谁都不绑定')
    @staticmethod
    def get_uuid():
        import uuid
        return uuid.uuid4()

import uuid
def get_uuid():
    return uuid.uuid4()
a = uuid.uuid4()
# p = Person(uuid.uuid4(),'nick',18)
# p = Person(get_uuid(),'nick',18)
p = Person('nick',18)
print(p.id)
print(Person.get_uuid())
# 面向对象高级:Person类也是一个特殊的对象

3. 面向对象串讲

# 面向对象最本质解决的是:提供可扩展性
# 类与对象
# 程序中必须先有类,再有对象

# 类中有属性,有方法
class Person:
    # 类属性
    school = 'oldboy'
    count = 0
    # 对象的绑定方法,初始化方法完成对象的初始化
    # 特殊之处,类实例化的时候自动调用
    def __init__(self,name='lqz'):
        Person.count += 1
        self.name = name
        self.age = 19
p = Person('nick')
# 对象是不能修改类属性的
# 类属性只能类来修改
print(Person.__dict__)
p.school = 'ppp'
print(p.__dict__)
# 绑定方法
# 定义在类内部,没有装饰器装饰的方法都是对象的绑定方法
# 需要对象来调用,对象调用的时候,会把自身传入
class Person:
    def __init__(self,name='lqz'):
        self.name = name
        self.age = 19
    def change_name(self,name):
        self.name = name

p = Person()
p.change_name('xxx')
# 本质就是  Person.change_name(p,'xxx')

# 对象交互
class Person:
    def __init__(self,name='lqz'):
        self.name = name
        self.age = 19
    def change_name(self,name):
        self.name = name.upper()

# 继承
# 减少代码冗余
# 选课系统,每个类应该有两个方法
# 方法一:根据名字获取对象
# 方法二:保存对象自身的功能
import pickle
import os
class BaseClass:
    @classmethod
    def get_obj_by_name(cls,name):
        # 字符串
        # admin
        class_name = cls.__name__.upper()
        # 文件路径
        path = os.path.join(class_name,name)
        with open(path,'rb') as f:
            obj = pickle.load(f)
        return obj

    def save(self):
        # 对象拿到类self.__class__
        cls = self.__class__
        class_name = cls.__name__.lower()
        #
        path = os.path.join(class_name,self.name)
        with open(path,'wb') as f:
            pickle.dump(self,f)
        return True


class Admin(BaseClass):
    def register(self,name,password):
        self.name = name
        self.password = password
        self.save()

class Student(BaseClass):
    def __init__(self):
        self.name = ''
        self.password = ''
        self.school = ''
        self.course_list = []
    def choose_course(self,course_name):
        self.course_list.append(course_name)
        self.save()

# 调用接口层的注册方法
def register_interface(name,pwd):
    obj = Admin.get_obj_by_name(name)
    if not obj:
        admin = Admin()
        admin.register(name,pwd)

#### 写在用户层
name = input('name')
password = input('password')

register_interface(name,password)

#### 接口层
def choose_course_interface(student_name,course_name):
    # 取到学生对象
    student = Student.get_obj_by_name(student_name)
    student.choose_course(course_name)

# 学生选课功能
# 用户功能层
# 假设课程全部打印出来了
course_name = 'linux'
student_name = 'bob'

choose_course_interface(student_name,course_name)

def check_all_student_course(student_name):
    student = Student.get_obj_by_name(student_name)
    return student.get_courses()

# 查询学生选的所有课程
check_all_student_course(student_name)


# 继承查找顺序(新式类,经典类)
# 广度优先和深度优先
# 在子类中调用父类的方法
# 指名道姓
# super(类名,对象).父类的方法名()  super 严格按照mro列表查找
# 派生
# 多态和多态性
# 控制子类必须实现父类的方法:abc模块,通过抛异常
# 鸭子类型:不用父类强制约束,人为约束

# 封装
# 组合也属于封装
# 隐藏属性和方法
# 用__放在属性或者方法面前:能把属性和方法隐藏
# 隐藏属性为了安全
# 隐藏方法为了隔离复杂度
# propertory:把方法包装成数据属性
# 修改:@方法名.setter+6
# 删除:@方法名.deleter

# classmethod:类的绑定方法
# staticmethod:静态方法(非绑定方法)
原文地址:https://www.cnblogs.com/yushan1/p/11432172.html