python金牌班第七周周末总结

面向对象前戏

1.我们在学习面相对像之前有一个推导过程如何将我们之前写的东西,从一串代码转向给对象服务。
2.实例
我们首先模拟了两个物种进行战斗的场景,然后我们发现我们都可以调用对方的数据因为我们的数据都是共享的,我们就需要将他绑定给她对应的对象然后就不会出现在这个对象外进行互相乱调用的情况。
3.代码
def Get_The_Butcher_of_the_sands(name, death_type, attack, health_point):
"""
# 首先创建荒漠屠夫的用户字典
:param name: 姓名
:param death_type:类型
:param attack: 攻击方式
:param health_point: 生命值
:return: 荒漠屠夫的字典
"""
The_Butcher_of_the_sands = { # 荒漠屠夫构建
'name': name,
'sands': death_type,
'the_tyrant_beat': attack,
'health_point': health_point
}
return The_Butcher_of_the_sands # p2 = get_The_Butcher_of_the_sands('renekton', 'soaring', 350, 3500)
# 3.让沙漠死神内瑟斯和荒漠屠夫雷克顿大战起来
def Desert_of_death_attack(Desert_of_death, The_Butcher_of_the_sands):
"""
内瑟斯打雷克顿
:param Desert_of_death:传内瑟斯数据
:param The_Butcher_of_the_sands:雷克顿数据
:return:
"""
print('即将被攻击的:%s, 当前血量 %s' % (The_Butcher_of_the_sands.get('name'),
The_Butcher_of_the_sands.get('health_point')))
The_Butcher_of_the_sands['health_point'] -= Desert_of_death['the_soul_from']
print('Desert_of_death:%s 使用 the_soul_from 攻击 The_Butcher_of_the_sands:%s ,The_Butcher_of_the_sands 掉血:%s 剩余血量:%s' %
(Desert_of_death.get('name'), The_Butcher_of_the_sands.get('name'), Desert_of_death.get('the_soul_from'),
The_Butcher_of_the_sands.get('health_point'))) def The_Butcher_of_the_sands_attack(The_Butcher_of_the_sands, Desert_of_death):
"""
雷克顿打内瑟斯
:param The_Butcher_of_the_sands:传内瑟斯数据
:param Desert_of_death:雷克顿数据
:return:
"""
print('即将被攻击的:%s, 当前血量 %s' % (Desert_of_death.get('name'),
Desert_of_death.get('health_point')))
Desert_of_death['health_point'] -= The_Butcher_of_the_sands['the_soul_from']
print('Desert_of_death:%s 使用 the_tyrant_beat 攻击 The_Butcher_of_the_sands:%s ,'
' The_Butcher_of_the_sands 掉血:%s 剩余血量:%s' % (The_Butcher_of_the_sands.get('name'),
Desert_of_death.get('name'), The_Butcher_of_the_sands.get('the_tyrant_beat'),
Desert_of_death.get('health_point'))) # 生产内瑟斯和雷克顿数据
p1 = Get_Desert_of_death('inside', 'soaring', 300, 4000)
p2 = Get_The_Butcher_of_the_sands('renekton', 'soaring', 350, 3500)
# 开打
Desert_of_death_attack(p1, p2)
"""
即将被攻击的:renekton, 当前血量 3500
Desert_of_death:inside 使用 the_soul_from 攻击 The_Butcher_of_the_sands:renekton ,The_Butcher_of_the_sands 掉血:300 剩余血量:3200
"""

两种编程思想

1.根据上方的演示我们明白了跟之前不太一样的编程思想,面向对象编程
2.面向过程编程,就是指我们之前写的代码,所有的数据都可以进行互相调用。
3.面向对象编程其实就是我们将他给绑定到一个地方也就是一个容器中,这个容器存储我们的数据和功能,我们虽然可以调用但是只要调用了那么你就是一个对象
4.面向对象和面向对象编程在我们的编程过程中都是一样的不存在哪个更好。并且经常在一起使用

对象与类型的概念

1.对象的概念
对象其实就是一个容器,我们可以在这个容器总存入数据和功能
2.类的概念
类其实就是类别和种类,我们可以也把他理解成一个容器,不过它内部的是多个对象,并且这些对象拥有相似的功能,而每个对象中只存了他自己所需要的数据,这样就极大的节省了内存,减少代码冗余。

对象与类的创建

1.什么是类
在我们现实生活中,一个人经常被成为是个体,而一群人则被成为群体也就是类。
2.对象是什么
对象其实就是将数据和功能绑定到一起,但是为了突出卖你想对象的形式然后python就专门为面向对象开发了以套专门用来操作秒你想对象的语法。
3.类的语法
class 类名:
# 类中对象的公共数据
# 类中对象的公共方法
3.1class是定义类的关键字
3.2类名和变量名函数名一样都需要做到见名知意并且建议首字母大写
3.3类体代码,也就是公共的数据和方法类体代码再定义阶段就会被执行

名称空间查找顺序

class Student: # 类的命名应该使用首字母大写

    school='清华大学' # 数据

    def choice(self): # 功能
print('choosing a course') # 选课 print(Student.__dict__) # 使用该方法查看名称空间 可以看成是一个字典
print(Student.__dict__['school']) # 使用字典的取值方式获取名字 # 清华大学
print(Student.__dict__.get('choice')) # 使用字典的取值方式获取名字
'''在面向对象编程中 想要获取名称空间中的名字 可以采用句点符'''
print(Student.school) # 清华大学
print(Student.choice) # <function Student.choice at 0x0000022915FDF820>
'''类实例化产生对象>>>: 类名加括号'''
stu1 = Student() # 清华大学
stu2 = Student() # <function Student.choice at 0x0000022915FDF820>
print(stu1.school) # 清华大学
print(stu2.school) # 清华大学
print(stu1) # <__main__.Student object at 0x000001D923B04A60>
print(stu2) # <__main__.Student object at 0x0000025E8A48F130>
print(stu1.__dict__, stu2.__dict__) # {} {}
print(stu1.school) # 清华大学
print(stu2.school) # 清华大学
print(stu1.choice) # <bound method Student.choice of <__main__.Student object at 0x0000022915EB2E80>>
print(stu2.choice) # <bound method Student.choice of <__main__.Student object at 0x0000022915EB2E80>>
Student.school = '北京大学' # 修改school键对应的值
print(stu1.school) # 北京大学
print(stu2.school) # 北京大学
"""
我们习惯将类或者对象句点符后面的东西称为属性名或者方法名
"""

对象的独有数据

1.方法一:
class Student:
school = '中国传媒大学'
def choice_course(self):
print('甄别课程')
obj1 = Student()
obj1.__dict__['name'] = 'joseph'
obj1.__dict__['age'] = 21
obj1.__dict__['hobby'] = 'read'
print(obj1.name) # joseph
print(obj1.age) # 21
print(obj1.hobby) # read
print(obj1.school) # 中国传媒大学
obj2 = Student()
obj2.__dict__['name'] = 'trump'
obj2.__dict__['age'] = 76
obj2.__dict__['hobby'] = 'golf'
print(obj2.name) # trump
print(obj2.age) # 76
print(obj2.hobby) # golf 2.方法二:
def init(obj, name, age, hobby):
obj.__dict__['name'] = name
obj.__dict__['age'] = age
obj.__dict__['hobby'] = hobby
Stu1 = Student()
Stu2 = Student()
init(Stu1, 'joseph', 21, 'read')
init(Stu2, 'Trump', 76, 'golf')
print(Stu1.__dict__) # {'name': 'joseph', 'age': 21, 'hobby': 'read'}
print(Stu2.__dict__) # {'name': 'Trump', 'age': 76, 'hobby': 'golf'} 3.方法三
class Student:
def __init__(self, name, age, hobby):
self.name = name # obj.__dict__['name'] = name
self.age = age # obj.__dict__['age'] = age
self.hobby = hobby # obj.__dict__['hobby'] = hobby
school = '中国传媒大学'
def choice_course(self):
print('选课')
stu1 = Student()
print(stu1.__dict__)
Student.__init__(stu1, 'joseph', 21, 'read')
print(stu1.__dict__)
print(stu1.name) stu1 = Student('joseph', 21, 'read')
print(stu1)
stu2 = Student('Trump', 76, 'golf')
print(stu2)

动静态方法

1.什么是方法
方法其实就是类体代码中编写的函数,每次传入时都会导出属于自己的数据,这种我们称之为方法。
2.绑定给对象的方法
对象调用的时候会将自身传入类体代码中,所以会产生一个独属于自己的数据也就是方法
3.静态方法(其实就是我们普通的有参函数)
class Game:
game_name = 'LOL'
# 绑定给对象的方法
def kill_enemy(self): # self来接收对象
print('你可也太强了', self)
@classmethod # 绑定给类的方法
def kill_nash_baron(cls): # 接受对象
print('大哥带带我', cls)
@staticmethod # 静态方法
def get_out(a, b): # 常规函数
print('自己一个人去玩吧,你可也太菜了')
Game1 = Game()
Game.kill_enemy(Game) # 你可也太强了 <class '__main__.Game'>
Game1.kill_enemy() # 你可也太强了 <__main__.Game object at 0x000001D86BB18C70>
Game.kill_nash_baron() # 大哥带带我 <class '__main__.Game'>
Game1.kill_nash_baron() # 大哥带带我 <class '__main__.Game'>
# 调用最普通的有参函数
Game.get_out(1, 2) # 自己一个人去玩吧,你可也太菜了
Game1.get_out(1, 2) # 自己一个人去玩吧,你可也太菜了

三大特征之传承

1.三大特征
1.1 继承
1.2 封装
1.3 多态
2.继承
继承其实和我们现实中的继承差不多其实就是我们从父辈那里的来他们的一些东西,在程序中其实也是一样的我们从父类代码中获取他的数据和功能,这种方法被我们称之为继承。
3.继承代码
class 类名(父类名):
pass
4.1 我们只需要在类名后方加一个括号
4.2 在括号内填入我们所需要的父类名就好了
4.3 父类是可以同时调用多个的只需要在父类名后面跟逗号就可以填写下一个父类名
class 类名 (父类名1, 父类名2, 父类名3......):
pass
我们在调用父类时一般是从左往右开始寻找
4.继承称谓
我们在继承中被继承的被成为:父类,基类和超类
在继承的类被称为:子类和派生类

继承的本质

1、所有的类都继承自object类,即所有的类都是object类的子类
2、子类一旦继承父类,则可以使用父类中除私有成员外的所有内
3、子类继承父类后并没有将父类成员完全赋值到子类中,而是通过引用关系访问调用
4、子类中可以定义独有的成员属性和方法
5、子类中定义的成员和父类成员如果相同,则优先使用子类成员
6、子类如果想扩充父类的方法,可以在定义新方法的同时访问父类成员来进行代码重用
7、可以使用 [父类名.父类成员] 的格式来调用父类成员,也可以使用[super().父类成员]的 格式来调用

不继承情况下下查找顺序

1.在没有继承任何类的情况下去查找顺序
class Game: # 创建一个类
game_name = 'LOL' # 命名类
def eat_river_crab(self): # 类中加函数也就是功能
print('吃河蟹') # 额吃game1 = Game() # 赋值
print(game1.game_name) # LOL 打印game1的值
game1.game_name = '云顶之奕' # 将game1的值修改
print(game1.game_name) # 云顶之奕 # 打印
game1print(Game.game_name) # LOL # 打印原本的Game的值也就是证明我使用后面赋值的值修改并不会修改原来数据的值,因为他已经保存到他自己的对象中

单继承情况下的查找顺序

1.单方面寻找
class A:
name = 'from A'
pass
class B(A):
name = 'from B'
pass
class C(B):
name = 'from C'
pass
class Myclass():
name = 'from Myclass'
pass
class Myclass2(C):
name = 'from Myclass2'
pass obj = Myclass()
print(obj.name) # from Myclass
obj.name = '浑身就像散架一样'
print(obj.name) # # from Myclass obj2 = Myclass2()
print(obj2.name) # 将自己的和C, B的注掉 from A
# 顺序 对象 >>> 类 >>> 父类
1.单方寻找但是自己也有值并且和第一种类重复
class A1:
def func1(self):
print('form func1')
def func2(self):
print('from func2')
def func3(self):
print('from func3')
self.func1() # obj.func1
class Myclass(A1):
def func1(self):
print('from Myclass')
obj = Myclass()
obj.func1() # from Myclass
obj.func3() # from func3,from Myclass 判断自己有没有(没有), 去父级中寻找找到了先打# 印来自func3,
# 然后往下走又是func1因为本质上其实还是obj.func1所以还是 自己的Myclass

多继承情况下的查找顺序

1.查找顺序内置方法mro()查看对象名的查找顺序
2.继承方式
非菱形继承(最后不会归总到一个我们自定义类上)
深度优先(每个分支都走到底 再切换)
菱形继承(最后归总到一个我们自定义类上)
广度优先(前面几个分支都不会走最后一个类 最后一个分支才会走)
3.代码
class A:
name = 'from A'
pass
class B():
name = 'from B'
pass
class C():
name = 'from C'
pass
class D(A):
# name = 'from D'
pass
class E(B):
# name = 'from E'
pass
class F(C):
# name = 'from F'
pass class Myclass(F):
# name = 'from Myclass'
pass obj = Myclass()
print(obj.name)
obj.name = '浑身就像散架一样'
print(obj.name) print(Myclass.mro()) # [<class '__main__.Myclass'>, <class '__main__.F'>, <class '__main__.C'>, <class 'object'>]
print(Myclass.__bases__) # (<class '__main__.F'>,)

经典类与派生类

1.经典类
什么都不继承
2.新式类
继承object或则其他类
3.类型存在
经典类只有在python2中才存在就是什么东西都没有继承。
新式类在我们的python2中和3中都有但是在py2中必须自己写后面的(object)而在python3中则不需要直接已经直接优化到内部不需要再也出来也默认有。
但是还是建议写成,增加兼容性
class Myfunc(object):
pass

派生类的概念

子类在内部写了和父类相同的代码,并且更加完善了代码扩展了其功能叫做派生。
class Person:
def __init__(self, name, age, hobby):
self.name = name
self.age = age
self.hobby = hobby class Teacher(Person):
def __init__(self, name, age, hobby, lever):
super().__init__(name, age, hobby)
self.lever = lever
class Student(Person):
pass t1 = Teacher('joseph', 21, 'read', 1/10)
p1 = Student('joseph', 21, 'read')
print(t1)
print(p1)
t1.__init__('joseph', 21, 'read', 1/10) class Myclass(list):
def append(self, value):
if value == 'joseph':
print('joseph 不许过')
return
super().append(value) object = Myclass()
object.append(520)
object.append(666)
object.append(999)
object.append('joseph') # joseph 不许过
object.append('Alice')
print(object) # [520, 666, 999, 'Alice']

三大特征之封装

1.封装其实就是将数据或者功能给她隐藏起来用户虽然也可以使用但是必须需要一些额外的操作打开对应的接口才可以去使用,而我们则需要在接口中添加操作去将他隐藏起来。
2.在类的定义中使用双下滑线开头的都是拥有隐藏属性的,后续的类或者对象都无法直接去获取和调用它
3.在我们的python中不会真正限制任何的代码,非常的贴心,所以我们要访问隐藏对象的时候也不是不能访问只是需要进行特殊处理一下
需要隐藏的数据:__变量名 >>> 调用数据: _类名__变量名
4.案例
class Student(object):
__school = '中国传媒大学'
## 公共功能
def __init__(self, name, age, hobby):
self.__name = name
self.__age = age
self.__hobby = hobby
# 接受学生信息
def check_info(self):
print("""
学生姓名:%s
学生年龄:%s
学生爱好:%s
""" %(self.__name, self.__age, self.__hobby))
# 学生修改信息
def set_info(self, name , age, hobby):
if len(name) == 0:
print('用户名不能为空')
return
if not isinstance(age, int):
print('年龄必须是数字')
return
if len(hobby) == 0:
print('爱好不能为空')
return
self.__name = name
self.__age = age
self.__hobby = hobby
stu = Student('joseph', 21, 'read')
print(stu)
print(stu.check_info)
print(stu.set_info('小娴是你嘛', 21, '今天刚好一年难受'))

propert伪装

1.可以理解为将方法伪装成数据
obj.name # 我们在调用数据的时候是需要使用句点符点的方式就可以调用
obj.func() # 而我们在调用方法的时候就需要给她加一个括号来调用,但是现在当我们有了伪装的时候只需要像调用数据一样只点一下就可以直接调用,给出一种错觉,这就是伪装
obj.func # 伪装后真假难辨,obj.func,雄兔脚朴素,雌兔眼迷离,双兔傍低走,安能辨我是雄雌。 身体健康指标:
体质指数(BMI) = 体重(kg) 身高 **2(m)
但是我感觉我好像不太健康的样子,太轻了
2.
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) p1 = Person('joseph', 60, 178)
res = p1.BMI
print(res)
print(p1.BMI)
print(p1.name)
print(p1.weight)
print(p1.height)
3.
class Foo:
def __init__(self, val):
self.__NAME = val # 隐藏属性 @property
def name(self):
return self.__NAME
@name.setter
def name(self, value):
if not isinstance(value, str): # 在设定值之前进行类型检查 接收
raise TypeError('%s must be str' % value) # 如果不是字符串自动报错,我们所给他设置的错误
self.__NAME = value # 通过类型检查后,将value存放到真是的位置也就是隐藏的self.__NAME @name.deleter
def name(self):
raise PermissionError('Can not delete') # 如果要删除name则报错 obj = Foo('joseph')
print(obj.name) # joseph
obj.name = 999 # 返回第一个报错也就是必须为字符串我们给她修改成整型
print(obj.name) # 打印 报错必须为字符串
del obj.name # 如果要删除的话直接捕获让他报错删除不了

三大特征之多态

1.什么是多态
多态其实就是一种事物的多种形态
就像水就有三种形态:固态(冰), 气态(水蒸气), 液态(肥宅快乐水)
动物也分为门,纲, 目, 科, 属, 种等分类
2.案例
# 警察抓罪犯,警察和两条警犬打击犯罪警犬分两种一种追击敌人另一种搜寻毒品,携带不同的警犬执行不同的工作
class Dog(object): # 定义父类
def work(self): # 提供解决方法
pass
# 定义子类,子类重写父类代码,并定义派生对象
class ArmyDog(Dog): # 继承上方父类
def work(self): # 重写同名的代码
print('追击罪犯...')
class DrugDog(Dog):
def work(self):
print('追击毒品...')
# 定义人类
class Person(object):
def work_with_Dog(self, dog): # 传入不同的类型,生成不通过的类型
dog.work() # 调用
ad = ArmyDog() # 调用不同对象
dd = DrugDog() police = Person()
police.work_with_Dog(ad) # 追击罪犯...
police.work_with_Dog(dd) # 追击毒品...
3.多态的本质
多态其实就是很多类共同调用同一个类,但是这些近似的功能都有共同的名字,我们无论拿到什么东西只要是可以套用的就可以直接去调用
4.抽象类
import abc
# 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法
def talk(self): # 抽象方法中无需实现具体的功能
pass
class Person(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准
def talk(self):
pass
def run(self):
pass
obj = Person()
4.鸭子类型
鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
我们并不关心对象是什么类型,到底是不是鸭子,只关心行为
鸭子类型在动态语言中经常使用,非常灵活,使得python不想java那样专门去弄一大堆的设计模式

文件属性

1.
操作系统
linux系统:一切皆文件
只要你能读数据 能写数据 那么你就是文件
内存
硬盘
class Txt: #Txt类有两个与文件类型同名的方法,即read和write
def read(self):
pass
def write(self):
pass class Disk: #Disk类也有两个与文件类型同名的方法:read和write
def read(self):
pass
def write(self):
pass class Memory: #Memory类也有两个与文件类型同名的方法:read和write
def read(self):
pass
def write(self):
pass
2. python:一切皆对象
只要你有数据 有功能 那么你就是对象
文件名 文件对象
模块名 模块对象

反射方法

1.反射是什么
反射其实就是一种使用字符串来操作对象数据和方法的的方式
对象通过字符串来自省的功能和方法
2.反射的使用方法
hasattr():判断对象是否含有某个字符串对应的属性
getattr():获取对象字符串对应的属性
setattr():根据字符串给对象设置属性
delattr():根据字符串给对象删除属性
3.getattr(核心) 判断类、对象或者模块中是否有相应的属性或方法。用法:getattr(obj,str,default=None) 判断obj中是否有str属性,有就返回,没有时有传入第三参数就返回第三参数,没有就报错。
class A:
name = 'joseph'
age = 21
print(getattr(A, 'name')) # joseph
print(getattr(A, 'language', 'notfound')) # notfound
4.setattr() 设置属性。第三参数为新的属性值
class A:
name = 'joseph'
age = 21
setattr(A, 'name', 'Alice')
setattr(A,'language', 'Chinese')
print(getattr(A, 'name')) # Alice
print(getattr(A, 'language', 'notfound')) # Chinese 5.hasattr
判断时候有某个属性,有就返回True,没有就返回False
class A:
name = 'joseph'
age = 21
if hasattr(A, 'name'):
print(getattr(A, 'name')) # joseph
6.delattr
删除某个属性
class A:
name = 'joseph'
age = 21 delattr(A, 'name')
print(hasattr(A, 'name')) # False
7.反射本文件
sys.modulses[__ name__]就是本文件对象。
import sys
class A:
def __repr__(self):
return '666'
if hasattr(sys.modules[__name__], 'A'):
print(getattr(sys.modules[__name__], 'A')) # <class '__main__.A'> # # 666

反射的实际应用

1.反射的用途
1、反射类中的变量 : 静态属性,类方法,静态方法
2、反射对象中的变量、对象属性、普通方法
3、 反射模块中的变量
4、反射本文件中的变量
2.应用
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()

反射的实战案例

1.案例1
import settings # 调用我们呢刚刚配置的文件
new_dic = {} # 制造一个空字典
print(dir(settings)) # 将settings内部的所有可以使用句点符点出来的功能都给他展示出来
# ['AGE', 'HOBBY', 'NAME', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
for i in dir(settings):
if i.isupper(): # 判断是否为纯大写,如果是纯大写的话那么就获取该大写名字所对应的值
value = getattr(settings, i) # 获得对所对应的属性
new_dic[i] = value # 生成一个字典属性将大写字母的值当作字典的k,然后属性当作v值并纯给之前定义的字典
print(new_dic) # 打印字典
2.模拟cmd终端命令
class windows():
def dir(self):
print('dir获取当前目录下所有文件名称')
def ls(self):
print('ls获取当前路径下所有文件名称')
def ipconfig(self):
print('ipconfig获取当前计算机的网卡信息')
obj = windows()
while True:
cmd = input('请输入您的指令')
if hasattr(obj, cmd):
cmd_name = getattr(obj,cmd)
cmd_name()
else:
print(f'{cmd} 不是内部命令或外部命令,也不是可运行的程序或批处理文件')

常见的魔法方法

1.常见魔法
class MyClass(object):
def __init__(self, name): # __init__() 用于初始化实例,所以该方法是在实例对象创建后被调用,它是实例级别的方法,用于设置对象属性的一些初始值
print('from__init__')
pass
self.name = name
def __str__(self): # print([对象]) 是个字符串的时候触发 __str__ 的执行
print('from__str__')
return f"对象名称:{self.name}"
def __call__(self, *args, **kwargs): # [对象] + ( ) 就触发 __call__ 的执行
print(args)
print(kwargs)
print('from __call__')
def __getattr__(self, item): # 在 [对象].[属性] 获取属性不存在的时候会触发它的执行
print('from __getattr', item)
return f'您想要获得的属性值:{item}不存在'
def __setattr__(self, key, value): # 在 [对象].[属性] = [值] 设置属性值的时候就会触发它的执行
print(key)
print(value)
print('from __setattr')
super.__setattr__(self, key, value)
def __del__(self): # 在 del [对象].[属性] 删除属性的时候会触发它的执行
print('from __del__')
pass
def __getattribute__(self, item): # 先执行 __getattribute__—>去类的名称空间找—>__getattr__(本质是去对象自己的名称空间找)
print('from __getattribute__')
return super(MyClass, self).__getattribute__(item)
def __enter__(self): # 上下文管理协议就是 with 语句, 为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__()和__exit__()方法
print('from __enter__')
def __exit__(self, exc_type, exc_val, exc_tb): # 如果__exit__()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行
print('from __exit__') obj = MyClass('joseph')
obj1 = MyClass('jason')
print(obj.name) # 获取对象拥有的属性名name
print(obj.age) # 获取对象不存在的属性名age
print(obj.pwd) # 获取对象不存在的属性名pwd
print(obj.__dict__)
print(obj.name)
# del obj
print(obj.name)
with obj as f:
print(f) with open() as f:
pass

元类简介

1.元类是什么
所有的对象都是实例化或者说是通过调用类而得到的,python中一切皆对象,通过class关键字定义的类本质也是对象,对象又是通过调用类得到的,因此通过class关键字定义的类肯定也是调用了一个类得到的,这个类就是元类。
2.怎么辨别元类
由于在python3中没有经典类和新式类的区别,因此python3中object是所有类的基类,那内置元类type又是什么?type是object类的类型,总结来说就是type是object的类型,同时,object又是type的基类,在python3中类和类型是同一种东西,因此对象.__class__和type(对象)得到的结果是一致的,object的基类为空,但是type的基类为object,但是object的类型又是type。
3.类型
object.__class__
<class 'type'>
type.__class__
<class 'type'>
object.__bases__()
type.__bases__
<class 'object'>
type(object)
<class 'type'>
type(type)
<class 'typ'>

产生类的两种方式

1.class关键字
class MyClass:
pass 2.利用元类type
type(类名,类的父类,类的名称空间) """
学习元类其实就是掌握了类的产生过程 我们就可以在类的产生过程中高度定制化类的行为
eg:
类名必须首字母大写
上述需求就需要使用元类来控制类的产生过程 在过程中校验
"""

元类的基本使用

1.只有继承了 type 的类才可以被称为元类
class MyMetaClass(type):
pass
2.如果像压迫切换产生类的元类的话只通过继承是不可以的,必须通过关键字的形式才可以进行转型
class MyClass(metaclass = MeMetaClass):
pass
3.__init__实例化
class MyMetaClass(type):
def __init__(self, what, bases=None, dict=None):
print('自己')
print('what', what) # 类名
print('bases', bases) # 类的父类
print('dict', dict) # 类的名称空间
if not what.istitel():
print('首字母必须大写如果不大写直接剔除')
raise Exception('首字母必须大写如果不大写直接剔除')
super().__init__(what, bases, dict)

元类的进阶操作

1.对象加括号执行产生的对象类内部加括号就可以操控内部对象
2.类加括号执行产生该类的元类里面的双下call
3.实例化对象并操控
class MyMetaClass(type):
def __call__(self, *args, **kwargs):
print('from __call__') # from __call__
if args:
raise Exception('需要根据形参传实参')
super().__call__(*args, **kwargs) # from __call__ class MyCalss(metaclass=MyMetaClass):
def __init__(self, name, age):
self.name = name
self.age = age
print('from __init__') # from __init__ obj1 = MyCalss('joseph', 21)
obj2 = MyCalss(name='joseph', age=21)

最新文章

  1. JavaScript代码优化指南
  2. UIActivityViewController 系统社交化 共享
  3. Majority Element II
  4. .net学习笔记---webconfig的读与写
  5. BpBinder 转换为 BpCameraService 流程
  6. FireFox背景亮度修改
  7. next permutaion算法
  8. Mac OS X中开启或关闭显示隐藏文件
  9. IOS做一个简单计算器
  10. laravel5.1关于lists函数的bug
  11. 20151225jquery学习笔记---折叠菜单UI
  12. POJ 3340 &amp;amp; HDU 2410 Barbara Bennett&amp;#39;s Wild Numbers(数学)
  13. T-SQL笔记总结(1)
  14. SQL菜鸟学习札记(二)
  15. HDU - 2154 线性dp
  16. 关于bootstrap框架美化的实例教程(python)
  17. Alpha冲刺随笔四:第四天
  18. 【代码笔记】iOS-MBProgressHUDDemo
  19. MyBatis3-动态SQL语句
  20. ashx文件获取$.ajax()方法发送的数据

热门文章

  1. 省HVV初体验(edu)
  2. 2021.03.20【NOIP提高B组】模拟 总结
  3. R数据分析:临床预测模型中校准曲线和DCA曲线的意义与做法
  4. CYaRon!语
  5. 数字图像处理-基于matlab-直方图均匀化,傅立叶变换,图像平滑,图像锐化
  6. 封装环形加载进度条(Vue插件版和原生js版)
  7. SAP 上传 函数 ALSM_EXCEL_TO_INTERNAL_TABLE 不稳定
  8. vue大型电商项目尚品汇(后台终结篇)day06 重磅!!!
  9. Burnside 引理与 P&#243;lya 定理
  10. Java 技术栈中间件优雅停机方案设计与实现全景图