上周内容回顾

编程思想

面向过程编程
	过程其实就是流程 面向过程编程其实就是执行一系列流程
就是按照指定步骤依次执行 最终可以得到想要的结果
'''面向过程编程相当于让你给出一个具体的解决方案'''
面向对象编程
	核心就是"对象"二字
	对象其实就是一个容器 里面将数据和功能都绑定到了一起
只负责创造 至于后续无人知晓
'''面向对象编程相当于让你创造一些事物后续不用你管'''
上述两种编程思想没有优劣之分 仅仅是使用场景不同
甚至很多时候是两者混合使用

对象与类的概念

对象:数据与功能的结合体
类:多个对象相同数据和功能结合体
    
类比学习法
	一个人   	对象
	多个人  	        人类
    
类主要用于记录读个对象相同的数据和功能
对象则用于记录多个对象不同的数据和功能

对象与类的创建

创建类的完整语法
class People:
    school = '清华大学' # 公共数据
    def course(self):  # 公共方法 
        print('选课')
 
1.class是定义类的关键字
2.People是类的名字
	类名与变量量一致 推荐首字母大写(为了区分)
3.类体代码
	公共数据\公共方法
ps:类体代码在类定义阶段就会执行

对象的独有数据

将数据和功能整合到一起将函数封装到学生类中 这样只有学生类产生的对象才有资格访问

class Student:  # 学生类
    def __init__(self, name, age, gender):
        self.name = name = name
        self.age = age
        self.gender = gender
# 左右两边的名字虽然一样 但是意思不一样 左边的其实是字典的键 右边的其实是实参
    school = '交通大学'  # 学生对象公共的数据
    def choice_course(self):  # 学生对象公共的方法
        print('正在选课')

stu1 = Student('joker', 18, 'male')
print(stu1)  # <__main__.Student object at 0x000001A8D3208518>
print(stu1.name)  # joker
print(stu1.age)  # 18
print(stu1.gender)  # male

对象的独有功能

针对对象独有的方法 我们无法真正实现
如果在全局则不是独有的
如果在类中则是公共的
python解释器针对上述问题添加了一个非常牛的特性
定义在类中的函数默认是绑定给对象的(相当于是对象独有的方法)

class Person:
    h_type = '人类'

    def __init__(self, name):  # 让对象拥有独有的数据
        self.name = name

    # 定义在类中的函数 我们称之为方法
    def eat(self): # 是多个对象公共的方法 也算多个对象独有的方法  对象来调用就会将对象当做第一个参数传入
        print('%s正在学习' % self.name)

    def others(self, name, b):
        print('%s好想睡觉鸭'%self.name)


p1 = Person('joker')
p1.eat()  # joker正在学习
p2 = Person('oscar')
p2.eat()  # oscar正在学习

动静态方法

专门针对类体代码中编写的函数

直接在类体代码中编写即可
对象调用会自动将对象当做第一个参数传入
类调用则有几个形参就传几个实参

一、绑定给对象的方法

class Person:
    h_type = '人类'
    def __init__(self, name):
        self.name = name
    def others(self, name, b):
        print('%s好想睡觉鸭'%self.name)
# 如何理解绑定二字
# 绑定只针对对象,对象来调这个方法不需要传参数
p3 = Person('lisa')
Person.eat(p3)  # lisa正在努力学习

# 但是其他人来调有几个参数就要传几个参数
p4 = Person('joker')
p4.others(1, 2)  # joker好想睡觉鸭

二、绑定给的方法

class Student:
    school = '北京大学'

    # 绑定给对象的方法
    def run(self):  # self用于接收对象
        print('跑的真快')

    @classmethod # 绑定给类的方法
    def eat(cls):  # cls用于接收类
        print('你可真有才')

stu1 = Student()  # 调用绑定给类的方法

# 类调用会自动将类当做第一个参数传入  等价于eat(Student)
Student.eat()  # 你可真有才

# 对象调用会自动将产出该对象的类当做第一个参数传入  等价于eat(Student)
stu1.eat()  # 你可真有才

三、静态方法(普普通通的函数)
当"@staticmethod"装饰后的方法(函数)不管是谁来调 有几个形参就要传几个

stu1 = Student() # 调用静态方法
class Student:
    school = '北京大学'

    # 绑定给对象的方法
    def run(self):  # self用于接收对象
        print('跑的真快')
    @staticmethod # 静态方法
    def sleap(a,b):
        print('赶紧去睡觉')
Student.sleap(1,2)  # 赶紧去睡觉
stu1.sleap(1,2)  # 赶紧去睡觉

面向对象三大特性之继承

继承、封装、多态

一、继承的含义

现在生活中继承就是人与与的资源关系
	eg:儿子继承了父亲的豪宅、跑车、家产 等等...
编程世界里继承就是类与类的数据关系
	eg:类A继承类B (A就拥有了类B所有数据和功能)

二、继承的目的

现在生活中就是占有别人的家产
	eg:亲身父亲、干爹干妈、傍富婆

三、继承的操作

class 类名(需要继承的类名):
    pass
	1.定义类的时候类名后加括号
	2.括号内填写你要继承的类名
	3.括号内可有填写多个类名 逗号隔即可
	eg:
        class MyClass(父类1,父类2,父类3,...)
        	pass

继承的本质

抽象:将多个类共同的数据或功能抽取出来形成一个基类

继承:从上往下白嫖各个基类里面的资源

对象:数据和功能的结合体
类:多个对象相同的数据和功能的结合体
父类:多个类相同的数据和功能的结合体

ps:类和父类最主要的功能其实就是节省代码

名字的顺序查找

一、在不继承的情况下名字的查找顺序

先从对象自身查找 没有的话 再去产生该对象的类中查找

class Student:
    school = '北京大学'
    def choice_course(self):
        print('正在选课')
stu1 = Student()
# 对象查找school 自身空间没有 所有查找的是类里面的
print(stu1.school)  # 北京大学

# 在自身空间产生了新的school
# 对象点名字并写了赋值符号和数据值 那么操作的肯定是自己的名称空间
stu1.school = '交通大学'
print(stu1.school)  # 交通大学

print(Student.school)  # 北京大学

二、单继承的情况下名字的查找顺序
先从对象自身查找 然后是产生该对象的类 然后是一个个父类

class A:
    name = 'from A'
class B(A):
    name = 'from B'
class C(B):
    name = 'from C'
class MyClass(C):
    name = 'from MyClass'

obj = MyClass()
# obj.name = '好想睡觉'
print(obj.name)

三、多继承的情况下名字的查找顺序

1.非菱形的继承(最后不会归总到一个我们自定的类上)
	深度优先(每个分支走到底 再切换)
2.菱形继承(做好归总到一个我们自定义的类上)
	广度优先(前面几个分支都不会走最后一个类 最后一个分支才会走)

经典类和新式类

经典类
	不继承object或其子类的类(什么类都不继承)
新式类
	继承了object或其子类的类
    
python3中所有的类都会默认继承object
	也就意味着python3中只有新式类
python2中只有经典类和新式类
	由于金典类没有核心功能 到了python3中就被砍掉了

派生方法

子类中定义类与父类一模一样的方法并且扩展该功能就叫派生方法

如果我们自己写子类需要用到父类的方法 并且还要基于该方法做扩展

可以使用关键字:supuer()

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

面向对象三大特性之封装

封装其实就是将数据或者功能隐藏起来

隐藏的目的不是让用户无法使用 而是给这些隐藏的数据开设特定的接口 让用户使用接口才能使用 我们可以在接口中扩展一些额外的操作

1.在类定义阶段使用双下划线开头的名字 都是隐藏的属性
后续类和对象都无法直接获取

2.在python中不会真正的限制任何代码
隐藏的属性如果真的需要访问 也可以 只不过需要做变形处理
__变量名 _类名__变量名
3.既然隐藏了 就不该使用变形之后的名字去访问 如果使用变形之后去访问这样就失去了隐藏的意义了

pioperty伪装属性

伪装的含义

可以简单的理解为 将方法伪装成数据
	obj.name   	# 数据只需要点名字
	obj.func()  # 方法至少还要加括号
伪装之后可以将func方法伪装成数据 obj.func

伪装装饰器  
    @property

如果用户要改属性的话必须按照指定数据类型进行更改
    @name.setter

如果用户想删除名字可以主动抛异常
    @name.deleter

面向对象三大特性之多态

多态是指一种事物的多种形态

比如动物:狗、猫、猪

class Animal(object):
    def spark(self):
        pass
class Cat(Animal):
    def spark(self):
        print(喵喵喵)
class Dog(Animal):
    def spark(self):
        print(汪汪汪)
def spark(Animal):
    Animal.spark()
cat = Cat()
spark(cat)   # 喵喵喵
dog = Dog()
dog.spark()  # 汪汪汪

面向对象之反射

反射是指通过'字符串'操作对象的数据或者方法

反射主要四个方法

方法关键字 使用详细
hasattr 判断对象是否含有某个字符串对应的属性
getattr 获取对象字符串的对应属性
setattr 根据字符串给对象设置属性
delattr 根据字符串给对象删除属性

反射实战案例

class FtpServer:
    def serve_forever(self):
        while True:
            inp = input('input your cmd>>: ').strip()
            cmd, file = inp.split()
            if hasattr(self, cmd):  # 根据用户输入的cmd,判断对象self有无对应的方法属性
                func = getattr(self, cmd)  # 根据字符串cmd,获取对象self对应的方法属性
                func(file)
    def get(self, file):
        print('Downloading %s...' % file)

    def put(self, file):
        print('Uploading %s...' % file)
obj = FtpServer()
obj.serve_forever()
'''
input your cmd>>: get a.txt  # 输入get会执行get下对应的功能
Downloading a.txt...
input your cmd>>: put b.txt  # 输入put会执行put下对应的功能
Uploading b.txt...
'''
 posted on 2022-07-31 19:15  Joker_Ly  阅读(11)  评论(0编辑  收藏  举报