当前位置:网站首页>Week 7 Review
Week 7 Review
2022-08-02 03:24:00 【candy prince】
面向对象前戏
实例:人狗大战
(1)将人的数据跟人的功能绑定到一起;
And only people can call functions of people.
(2)将狗的数据跟狗的功能绑定到一起;
And only dogs can call dog functions.
(3)The operation that we bind data and functionality together is named:‘’面向对象编程‘’本质:将特定的数据与特定的功能绑定到一起,In the future, they can only call each other.
编程思想
1.编程思想之面向过程编程
过程就是流程,面向过程编程其实就是在执行一系列的流程.
eg:注册功能;登录功能…
就是按照指定的步骤依次进行,最终就可以得到想要的结果.
2.编程思想之面向对象编程
The core is the word object;
对象其实就是一个容器,It binds data and functionality together.
eg:游戏人物…
只负责创造出该人物以及该人物具备的功能.
3.总结
面向过程编程相当于让你给出一个问题的具体解决方案;
面向对象编程相当于让你创造出一些事物之后不用你管;
上述两种编程思想没有优劣之分,It's just that the usage scenarios are different.
对象与类的概念
1.概念
对象:数据与功能的结合体
类:Multiple objects with the same data
2.类比学习法
类主要用于记录Multiple objects with the same data和功能
对象则用于记录多个对象不同的数据和功能
对象与类的创建
1.对象与类的说明
In real life, the theory is that there should be an individual(对象)再有一个个的群体(类)
在编程世界中必须要先有类才能产生对象
2.面向对象在python中的应用
面向对象编程本质就是将数据和功能绑定到一起,但是为了突出面向对象编程的形式,pythonSpecifically developed a set of operations specifically for object-oriented.
3.python中创建类的完整语法
class People:
#学生对象公共的数据
#学生对象公共的方法
(1)class是定义类的关键字
(2)People是类的名字Class names are named in the same way as variable names,并且推荐首字母大写
(3)类体代码公共的数据\公共的方法,类体代码在类定义阶段就会执行.
举个栗子:class Student: # 学生对象的公共数据 school = '清华大学' # 学生对象公共的方法 def choice_course(self): print('正在选课') # 查看名称空间的方法 print(Student.__dict__) # 使用该方法查看名称空间 可以看成是一个字典 print(Student.__dict__['school']) # 使用字典的取值方式获取名字 print(Student.__dict__.get('choice_course')) # 使用字典的取值方式获取名字
4.句点符
在面向对象编程中,想要获取名称空间中的名字,可以采用句点符.
print(Student.school) print(Student.choice_course)
5.类实例化对象>>>>:类名加括号
stu1 = Student() stu2 = Student() print(stu1.school) # 清华大学 print(stu2.school) # 清华大学 Student.school = '北京大学' # 修改school键对应的值 print(stu1.school) # 北京大学 print(stu2.school) # 北京大学
Object-specific data and functionality
1.The example is deduced as follows:
(1)先定义一个类:# 学生类 class Student: # 学生对象公共的数据 school = '清华大学' # 学生对象公共的方法 def choice_course(self): print('正在选课')
(2)直接利用__dict__方法朝字典添加键值对:
obj1 = Student() obj1 = Student() obj1.__dict__['name'] = 'jason' # 等价于 obj1.name = 'jason' obj1.__dict__['age'] = 18 # 等价于 obj1.age = 18 obj1.__dict__['gender'] = 'male' # ... print(obj1.name) print(obj1.age) print(obj1.gender) print(obj1.school) obj2 = Student() obj2.__dict__['name'] = 'kevin' obj2.__dict__['age'] = 28 obj2.__dict__['gender'] = 'female' print(obj2.name) print(obj2.age) print(obj2.gender) print(obj2.school) """ jason 18 male 清华大学 kevin 28 female 清华大学 """
(3)将添加独有数据的代码封装成函数:
def init(obj,name,age,gender): obj.__dict__['name'] = name obj.__dict__['age'] = age obj.__dict__['gender'] = gender stu1 = Student() stu2 = Student() init(stu1,'jason',18,'male') init(stu2, 'kevin',28,'female') print(stu1.__dict__) print(stu2.__dict__) """ {'name': 'jason', 'age': 18, 'gender': 'male'} {'name': 'kevin', 'age': 28, 'gender': 'female'} """
(4)init函数是专用给学生对象创建独有的数据,其他对象不能调用>>>:Object-oriented thinking integrates data and functions and encapsulates functions into student classes,In this way, only objects of the student class have access to it.
class Student: """ 1.先产生一个空对象 2.自动调用类里面的__init__方法 将产生的空对象当成第一个参数传入 3.将产生的对象返回出去 """ def __init__(self, name, age, gender): self.name = name # obj.__dict__['name'] = name self.age = age # obj.__dict__['age'] = age self.gender = gender # obj.__dict__['gender'] = gender # 左右两边的名字虽然一样 但是意思不一样 左边的其实是字典的键 右边的其实是实参 # 学生对象公共的数据 school = '清华大学' # 学生对象公共的方法 def choice_course(self): print('正在选课') # stu1 = Student() # print(stu1.__dict__) # Student.init(stu1, 'jason', 18, 'male') # print(stu1.__dict__) # print(stu1.name) stu1 = Student('jason', 18, 'male') print(stu1) stu2 = Student('kevin', 28, 'female') print(stu2) """ jason 清华大学 """
2.The kinetic energy unique to the object
针对对象独有的方法,We can't really make it happen:
如果在全局则不是独有的;如果在类中则是公共的.在python中存在一个特性,相当于是对象独有的方法,就是定义在类中的函数默认都是绑定给对象的.
class Person: h_type = '人类' def __init__(self, name): # 让对象拥有独有的数据 self.name = name # 定义在类中的函数 我们称之为方法 def eat(self): # 是多个对象公共的方法 也算多个对象独有的方法 对象来调用就会将对象当做第一个参数传入 print('%s正在干饭'%self.name) p1 = Person('jason') p1.eat() # eat(p1) # jason正在干饭 p2 = Person('kevin') p2.eat() # eat(p2) # kevin正在干饭 # 如何理解绑定二字 p3 = Person('oscar') Person.eat(p3) # oscar正在干饭 ''' jason正在干饭 kevin正在干饭 oscar正在干饭 '''
动静态方法
There are three types of dynamic and static methods:主要是专门针对在类体代码中编写的函数.
(1)绑定给对象的方法:
直接在类体代码中编写即可;
对象调用会自动将对象当做第一个参数传入;
When a class call has several formal parameters, pass several formal parameters.class Student: school = '清华大学' # 绑定给对象的方法 def run(self): # self用于接收对象 print('老六赶紧跑!!!', self) stu1 = Student()
(2)绑定给类的方法:
类的调用会自动将类当做第一个参数传入;
使用语法糖——@classmethodclass Student: school = '清华大学' # 绑定给对象的方法 def run(self): # self用于接收对象 print('老六赶紧跑!!!', self) @classmethod # 绑定给类的方法 def eat(cls): # cls用于接收类 print('老六你可真有才', cls) stu1 = Student() # 调用绑定给类的方法 Student.eat() # 类调用会自动将类当做第一个参数传入 >eat(Student) ''' 老六你可真有才 <class '__main__.Student'>''' stu1.eat() # 对象调用会自动将产生该对象的类当做第一个参数传入 eat(Student) '''老六你可真有才 <class '__main__.Student'>'''
(3)静态方法(普普通通的函数)
使用语法糖@startmethodclass Student: school = '清华大学' @staticmethod # 静态方法 def sleep(a, b): # 无论谁来调用都必须按照普普通通的函数传参方式 print('老六快去睡觉吧') stu1 = Student() # 调用静态方法 # 类调用 Student.sleep(1,2) # 对象调用 stu1.sleep(1, 2)
面向对象三大特性之继承
1.继承的含义
(1)在现实生活中继承其实就是用来描述人与人之间资源的关系
eg:儿子继承父亲的财产(拥有了父亲所有的资源)
(2)在编程世界里继承其实就是用来描述类与类之间数据的关系
eg:类A继承类B(拥有了类B里面所有的数据和功能)
2.继承的目的
(1)现实生活中继承就是想占有别人的财产
eg:亲身父亲 干爹 干妈 富婆
(2)编程世界里继承就是为了节省代码编写
eg:可以继承一个类 也可以继承多个类
3.继承的操作
class 类名(父类): pass
(1)定义类的时候在类名后加括号;
(2)括号内填写你需要继承的类名;
(3)括号内可以填写多个父类,逗号隔开即可用法
# 父类 class Father: money = 1000000000 def run(self): print('豪车别墅') # 子类 class Son(Father): pass print(Son.money) # 1000000000 Son.run(11) # 豪车别墅
4.继承类的说明
(1)我们将被继承的类称之为: 父类或基类或超类;
(2)我们将继承类的类称之为: 子类或派生类;
(3)查找父类要按括号内从左到右查找(If there is something in it, it will not be obtained from the parent class)
5.继承的本质
(1)抽象和继承
抽象:将多个类共同的数据或功能抽取出来形成一个基类;
继承:The resources of each base class are prostituted from top to bottom.
(2)举个栗子class Person: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender class Teacher(Person): def teach_course(self): print('老师上课') class Student(Teacher): def choice_course(self): print('学生选课') stu1 = Student('jason',18,'male') print(stu1.__dict__) # {'name': 'jason', 'age': 18, 'gender': 'male'}
6.名字的查找顺序
敲重点:Mainly involves object lookup names,Then it's almost always the object itself, then the class and finally the parent class!!!
(1)Name lookup order without inheritance——先从对象自身查找,没有的话再去产生该对象的类中查找.
(2)Name lookup order in the case of single inheritance——先从对象自身查找,然后是产生该对象的类,然后是一个个父类.
(3)Name lookup order in case of multiple inheritance——The first non-diamond inheritance(最后不会归总到一个我们自定义类上),深度优先(每个分支都走到底,在切换);The second type of diamond inheritance(最后归总到一个我们自定义类上),广度优先(前面几个分支都不会走最后一个类,最后一个分支才会走)
7.经典类与新式类
(1)概念
经典类:不继承object或其子类的类
新式类:继承了object或其子类的类
(2)推荐用法
When defining the class later,如果没有想要继承的父类,一般推荐以下写法:# 目的是为了兼容python2版本解释器 class MyClass(object): pass
派生方法
子类中定义类与父类一模一样的方法并且扩展了该功能>>>:派生
1.派生的作用——super()内置属性class Person: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender class Teacher(Person): def __init__(self,name,age,gender,level): super().__init__(name,age,gender) # super专门用于子类调用父类的方法 self.level = level # 自己补充一些的 class Student(Person): pass
2.Derivative practical exercises(重要)
(1)前戏:Some data types are not working properlyjson序列化import datetime import json d = { 't1':datetime.datetime.today(), 't2':datetime.date.today() } res = json.dumps(d) print(res) ''' TypeError: Object of type 'datetime' is not JSON serializable '''
The data type here cannot be readjsonSerialization gives the following solution(派生方法):
查看dumps内JSONEncoder源码发现序列化报错是有default方法触发的,If you want to avoid errors,A derived method pair is requireddefault方法做修改.
import datetime import json d = { 't1':datetime.datetime.today(), 't2':datetime.date.today() } class MyJsonEncode(json.JSONEncoder): def default(self, o): '''o就是json即将要序列化的数据''' if isinstance(o, datetime.datetime): return o.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(o, datetime.date): return o.strftime('%Y-%m-%d') # 如果是可以序列化的类型 那么不做任何处理 直接让它序列化即可 return super().default(o) res = json.dumps(d, cls=MyJsonEncode) print(res) json.dumps(d, cls=MyJsonEncode)
面向对象三大特性之封装
1.封装的概念
封装其实就是将数据或者功能隐藏起来;隐藏的目的不是让用户无法使用,而是给这些隐藏的数据开设特定的接口,让用户使用接口才可以去使用,我们在接口中添加一些额外的操作.
2.封装隐藏特性
(1)在类定义阶段使用双下划线开头的名字都是隐藏属性.
后续类和对象都无法直接获取
(2)在python中不会真正的限制任何代码.
隐藏的属性如果真的需要访问,也可以经过变形处理.不过这样就失去了隐藏的意义!!!
3.封装实例
class Student(object): __school = '清华大学' def __init__(self, name, age): self.__name = name self.__age = age # 专门开设一个访问学生数据的通道(接口) def check_info(self): print(""" 学生姓名:%s 学生年龄:%s """ % (self.__name, self.__age)) # 专门开设一个修改学生数据的通道(接口) def set_info(self,name,age): if len(name) == 0: print('用户名不能为空') return if not isinstance(age,int): print('年龄必须是数字') return self.__name = name self.__age = age stu1 = Student('jason', 18) print(stu1._Student__name) ''' jason ''' # 修改名字方法: stu1.set_info('kevin',20) print(stu1._Student__name) ''' kevin'''
4.python伪装属性
(1)伪装的含义:
可以简单地理解为将方法伪装成数据.
数据只需要点名字:obj.name
方法至少还要加括号:obj.func()
伪装之后可以将func方法伪装成数据:obj.func(2)@propertysyntactic sugar————p1.BMI #直接调用
class Person: def __init__(self, name, weight, height): self.name = name self.weight = weight self.height = height @property def BMI(self): return self.weight / (self.height ** 2) # 添加装饰器@property之后 p1 = Person('jason', 78, 1.83) print(p1.BMI) # 23.291229956104985 print(p1.name) # jason
面向对象三大特性之多态
1.多态的字面含义
多态:一种事物的多种形态
水:液态 气态 固态
动物:人 狗 猫 猪
2.多态实例
实例一:引出之不同动物叫声用一个方法(spark)调用:""" eg: 无论是鸡鸭狗猪,只要叫就调用固定的属于叫的功能!!! """ class Animal(object): def spark(self): pass class Cat(Animal): def spark(self): print('喵喵喵') class Dog(Animal): def spark(self): print('汪汪汪') c1.spark() # 喵喵喵 d1.spark() # 汪汪汪
实例二:不论是元组,列表还是字典,统计长度都是len方法调用.
l1 = [11, 22, 33, 44] d1 = { 'name': 'jason', 'pwd': 123, 'hobby': 'raed'} t1 = (11, 22, 33, 44) print(len(l1)) print(len(d1)) print(len(t1))
3.鸭子类型
大白话解释:只要你长得像鸭子,走路像鸭子,说话像鸭子,那么你就是鸭子.class Teacher: def run(self):pass def eat(self):pass class Student: def run(self):pass def eat(self):pass
4.Polymorphism in different systems
(1)linux系统:一切皆文件
As long as the data can be read,写数据,So long is the file——硬盘;内存
(2)python中:一切皆对象
There is only data,有功能,Then there is the object——文件名:文件对象;模块名:模块对象.
面向对象之反射
1.反射的含义
通过字符串来操作对象的数据或方法
2.反射的四个方法
hasattr():判断对象是否含有某个字符串对应的属性
getattr():获取对象字符串对应的属性
setattr():根据字符串给对象设置属性
delattr():根据字符串给对象删除属性
3.反射用法
需求里面只要看到…字符串或者…对象那么肯定需要使用反射!!!
4.Reflex practice
(1)练习一:加载配置文件纯大写的配置# 配置文件加载:获取配置文件中所有大写的配置 小写的直接忽略 组织成字典 import settings new_dict = { } # print(dir(settings)) # dir获取括号中对象可以调用的名字 # ['AGE', 'INFO', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'desc', 'name'] for i in dir(settings): if i.isupper(): # 如果名字是纯大写 那么获取该大写名字对应的值 'AGE' 'INFO' v = getattr(settings, i) new_dict[i] = v print(new_dict)
(2)练习二:模拟操作系统cmd终端执行用户命令
class WinCmd(object): def dir(self): print('dir获取当前目录下所有的文件名称') def ls(self): print('ls获取当前路径下所有的文件名称') def ipconfig(self): print('ipconfig获取当前计算机的网卡信息') obj = WinCmd() while True: cmd = input('请输入您的命令>>>:') if hasattr(obj, cmd): cmd_name = getattr(obj, cmd) cmd_name() else: print('%s 不是内部或外部命令,也不是可运行的程序或批处理文件' % cmd)
面向对象魔法方法
1.魔法方法概念
魔法方法就是类中定义双下方法,之所以会叫魔法方法原因是这些方法都是到达某个条件自动触发,无需调用.
eg:__init__方法再给对象设置独有数据的时候自动触发(实例化)
2.常见的魔法方法
项目 Value 触发条件 __ init__ 对象实例化的时候自动触发 实例化对象的时候自动触发 __ str__ 对象被执行打印(print、前端展示)操作的时候自动触发,该方法必须返回字符串类型的数据,很多时候用来更加精准的描述对象 对象被执行打印操作的时候会自动触发 __ del__ 对象被执行(被动、主动)删除操作之后自动执行 对象在被删除(主动 被动)的时候自动触发 __ getattr__ 对象查找不存在名字的时候自动触发 当对象获取一个不存在的属性名 自动触发 __ setattr__ 对象在执行添加属性操作的时候自动触发 >>> obj.变量名=变量值 对象操作属性值的时候自动触发>>>: 对象.属性名=属性值 __ call__ 对象被加括号调用的时候自动触发 对象加括号调用 自动触发该方法 __ enter__ 对象被执行with上下文管理语法开始自动触发 ,该方法返回什么as后面的变量名就会得到什么 对象被with语法执行的时候自动触发 __ exit__ 对象被执行with上下文管理语法结束之后自动触发 对象被with语法执行并运行完with子代码之后 自动触发 __ getattribute__ 只要对象查找名字无论名字是否存在都会执行该方法,如果类中有__getattribute__方法 那么就不会去执行__getattr__方法 对象获取属性的时候自动触发 __ new__ 在类被实例化前,最先被执行的方法,主要用来去创建一个完全空白的对象
产生类的两种方式
1.方式一:class关键字
class MyClass: pass
2.方式二:利用元类type
type(类名,类的父类,类的名称空间)
class MyClass1: pass print(MyClass1.__dict__,MyClass1) # {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'MyClass1' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass1' objects>, '__doc__': None} <class '__main__.MyClass1'> res = type('MyClass2',(),{ }) print(res.__dict__,res) # {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'MyClass2' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass2' objects>, '__doc__': None} <class '__main__.MyClass2'> obj = res() print(obj) # <__main__.MyClass2 object at 0x00000209EA66D390>
元类简介
1.元类的引出
(1)基础阶段我们使用type来查找数据的数据类型;
(2)但是学了面向对象之后,发现查看的不是数据类型,而是数据所属的类;s1 = '哈哈哈 今天下午终于可以敲代码了!!!' l2 = [60, 80, 100, 120, 150, 200] print(type(s1)) # <class 'str'> print(type(l2)) # <class 'list'>
(3)而是数据所属的类型,其实本质还是通过各个类产生了对象.
class str: pass h = 'hello' str('hello')
(4)我们可以理解为type用于查看产生当前对象的类是谁
class MyClass: pass obj = MyClass() print(type(obj)) # 查看产生对象obj的类:<class '__main__.MyClass'> print(type(MyClass)) # 查看产生对象MyClass的类:<class 'type'>
(5)通过上述推导,得出最后结论,自定义的类都是由type类产生的,我们将产生类的类称之为“元类!!!”
2.自定义指定元类
class MyMetaClass(type): pass """只有继承了type的类才可以称之为是元类""" class MyClass(metaclass=MyMetaClass): pass """如果想要切换产生类的元类不能使用继承 必须使用关键字metaclass声明"""
3.元类中initUsed to instantiate classes
class MyMetaClass(type): def __init__(self, what, bases=None, dict=None): # print('别晕') # print('what', what) 类名 # print('bases', bases) 类的父类 # print('dict', dict) 类的名称空间 if not what.istitle(): # print('首字母必须大写 你会不会写python 面向对象学过吗 lowB') raise Exception('首字母必须大写 你会不会写python 面向对象学过吗 lowB') super().__init__(what, bases, dict) class Aaa(metaclass=MyMetaClass): pass # 没有报错,说明实例化类成功
4.元类不单单可以控制类的产生过程,其实也可以控制对象的!!!
对象加括号执行产生该对象类里面的双下call
类加括号执行产生该类的元类里面的双下call
class MyMetaClass(type): def __call__(self, *args, **kwargs): print('__call__') if args: raise Exception('必须用关键字参数传参') super().__call__(*args, **kwargs) class MyClass(metaclass=MyMetaClass): def __init__(self, name, age): self.name = name self.age = age print('__init__') # 需求:实例化对象 所有的参数都必须采用关键字参数的形式 obj = MyClass('jason', 18) # obj = MyClass(name='jason', age=18)
5.元类总结
如果我们想高度定制对象的产生过程:可以操作元类里面的__call__.
如果我们想高度定制类的产生过程:可以操作元类里面的__init__.
边栏推荐
猜你喜欢
赶紧进来!!!教你用C语言写三子棋小游戏
【遥控器开发基础教程3】疯壳·开源编队无人机-ADC(摇杆控制)
I will give you a chance to interview in a big factory. Can you interview?Come in and see!
EF Core:基于关系的复杂查询 区分IEnumerable和IQueryable
DOM destruction and reproduction experiment
JDBC--Druid数据库连接池以及Template基本用法
分布式领域最重要的一篇论文,到底讲了什么?
嵌入式分享合集25
OD-Model [4]: SSD
两对象数组比较拿出不同值方法
随机推荐
OD-Model【4】:SSD
(Reposted) The relationship between hashcode and equals
蓝鲸DevOps荣获平台类工具企业选择率第一
CV-Model【4】:MobileNet v3
STM32——LCD—TFTLCD原理与配置介绍
嘉为蓝鲸携手东风集团、上汽零束再获信通院四项大奖
RHCSA第三天
TRICK第二弹
Double Strings (别总忘记substr)
OD-Model [4]: SSD
MySQL中的各种锁(行锁、间隙锁、临键锁等等LBCC)
输入延迟切换系统的预测镇定控制
MySQL中根据日期进行范围查询
我的两周年创作纪念日
Ribbon本地实现负载均衡
每日练习------有n个整数,使其前面各数顺序向后移m个位置,最后m个数变成最前面的m个数
弹性盒子flex属性
基于libmodbus库实现modbus TCP/RTU通信
两对象数组比较拿出不同值方法
第二章——堆栈、队列