【23.绑定方法与非绑定方法介绍】
再类的内部的定义的函数分为两大类:
1.绑定方法:
绑定到对象的方法:直接用def做的函数属性,类内部定义的函数,如果没有绑定装饰器,就是给对象使用的函数,绑定给谁就给谁来调用
绑定到类的方法
2.非绑定方法:不与类或者对象绑定
# 绑定对象的方法,类去访问自己的函数属性的时候就是一个普通的函数,没有自动调用的方式
# 绑定给谁,就应该谁来调用就会把调用者当做第一个参数自动传入
# class Foo:
# def __init__(self, name):
# self.name = name
#
# def tell(self):
# print('名字是%s' %self.name)
#
# f = Foo('panda')
# print(f.tell)
# -------------------------------------------------------------------
# 绑定到类:在类的内部定义的,被装饰器classmethod修饰的方法
# class Foo:
# def __init__(self, name):
# self.name = name
#
# def tell(self):
# print('名字是%s' %self.name)
#
# @classmethod
# def func(cls):
# print(cls)
#
# Foo.func()
# print(Foo)
# -------------------------------------------------------------------
# 非绑定方法:不与类或者对象绑定,没有自动传值,谁都可以用,就相当于普通函数,一点都没有绑定关系
# 就是类中定义的普通工具
class Foo:
def __init__(self, name):
self.name = name
def tell(self):
print('名字是%s' %self.name)
@staticmethod
def func1(x,y):
return x+y
f = Foo('panda')
print(Foo.func1(1,2))
print(f.func1(1,3))
【24.绑定方法与非绑定方法】
什么场景下使用绑定方法和非绑定方法
import settings
class People:
def __init__(self,name, age, sex):
self.name = name
self.age = age
self.sex = sex
self.id = self.create_id()
def tell_info(self): #绑定到对象的方法
print('Name %s Age %s Sex %s' % (self.name, self.age, self.sex))
@classmethod
def from_conf(cls):
obj = cls(
settings.name,
settings.age,
settings.sex
)
return obj
@staticmethod
def create_id():
import hashlib
import time
m = hashlib.md5(str(time.time()).encode('utf-8'))
return m.hexdigest()
# p1 = People('panda', 18, '男')
# 绑定给对象就由对象来调用,自动将对象本身当做第一个参数传入
# p1.tell_info() #tell_info(p1)
# 新需求:从配置文件里读取信息来实例化对象
# p2 = People(settings.name, settings.age, settings.sex)
# p2.tell_info()
#---------------------------------------------------#
# 绑定给类
# p = People.from_conf()
# p.tell_info()
#---------------------------------------------------#
# 非绑定方法,不与类或者对象绑定,谁都可以调用,没有自动传入值的功能
# p1 = People('panda',20,'male')
# p2 = People('pandaboy',10,'male')
# print(p1.id)
# print(p2.id)
【25.反射】
用户的输入就会变成字符串,input方法就是会转换成字符串的形式
如果通过用户的输入,让用户通过字符串调用类的属性
反射:通过字符串来映射到对象的属性
# class People:
# county = 'China'
# def __init__(self,name, age):
# self.name = name
# self.age = age
# def talk(self):
# print('%s is talking' %self.name)
#
# obj = People('panda', 10)
# print(obj.name)
# obj.talk()
# 用户的输入就会变成字符串,input方法就是会转换成字符串的形式
# 如果通过用户的输入,让用户通过字符串调用类的属性
# 1.hasattr(obj,str)>>判断obj下到底有没有str的参数属性,本质上就是判断字典里有没有str的属性(obj.__dict__(str))>>返回的值是布尔值(True/False)(判断有没有)
# 2.getattr(obj,str,default)>>直接显示str属性的结果,如果没有就报错,default就是直接赋值None(设置)
# 3.setattr(obj,'sex','male')>>等同于obj.sex = male设置对象的值(修改和新增)
# 4.delattr(obj, 'age')>>等同于del obj.age删除对象的值(删除)
# print(getattr(People,'county'))
反射的应用
class Service:
def run(self):
while True:
cmd = input('>>>').strip()
print(cmd)
if hasattr(self,cmd):
func = getattr(self,cmd)
func()
def get(self):
print('get.....')
def put(self):
print('put.....')
obj = Service()
obj.run()
【26.内置方法介绍】
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
对象到底是不是类的实例
class Foo:
pass
obj = Foo()
print(isinstance(obj,Foo))
issubclass(sub, super)检查sub类是否是 super 类的派生类
class Foo:
pass
class Bar(Foo):
pass
print(issubclass(Bar,Foo))
Item系列
把对象模拟成python的字典类型的数据实现访问的格式,会把obj模拟成字典的形式
class Foo:
def __init__(self,name):
self.name = name
def __getitem__(self, item):
# print('Get item.....')
# print(item)
return self.__dict__.get(item)
def __setitem__(self, key, value):
# print('Set item.....')
# print(key,value)
self.__dict__[key] = value
def __delitem__(self, key):
self.__dict__.pop(key)
obj = Foo('panda')
#实现obj.name的实现方式,
# 查看属性
print(obj['name'])
#设置赋值方式,设置属性
obj['sex'] = 'male'
print(obj['sex'])
# 删除属性
del obj['name']
print(obj['name'])
__str__方法改变对象的字符串显示,会在打印对象的时候触发,把返回结果(必须是字符串)返回
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return '<name %s age %s>' % (self.name, self.age)
obj = People('panda',10)
print(obj)
__del__方法:如果在类的内部调用了__del__方法,这个方法就会绑定给对象,在对象被删除的时候会自动先触发,就会调用垃圾回收机制,即使你不调用,也会在删除对象的时候自动触发__del__方法,
# ___模拟打开文件的操作,在python内部结束了以后,会自动触发__del__的操作,自动回收操作系统资源
class Open:
def __init__(self, filename):
print('open file...')
self.filename = filename
def __del__(self):
print('Finish !')
f = Open('test.txt')
print('At the end')
【27.元类介绍】
面向对象高级难点:元类(metaclass)
储备知识exec--->把字符串里的内容提取出来直接执行
参数1:字符串形式的命令
参数2:全局作用域(字典形式),可以定制一个全局作用域(如果不指定,默认使用globals())
参数3:局部作用域(字典形式),如果不指定默认就使用loacals()
实例化了元类得到了元类的对象,元类的对象实际上就是利用class声明的一个类
g = {
'x':1,
'y':2,
}
l = {}
exec('''
global x,m
x = 10
m = 100
z = 3
''',g, l)
print(g.get('m'))
print(l)
# python中一切皆对象,对象可以怎么使用?
# 1.都可以被引用,x = obj
# 2.都可以当做函数的参数传入
# 3.都可以当做函数的返回值
# 4.都可以当做容器类型的元素,l = [func, time, obj, 1]
# 产生类的类称之为元类,默认所有用class定义的类,他们得元类就是type
# 定义类有两种实现方式
# 1.class关键字的方式
# class Chinese:
# country = 'China'
# def __init__(self,name, age):
# self.name = name
# self.age = age
# def talk(self):
# print('%s is talking' % self.name)
# 2.type元类的产生
# 定义类的三要素
# 1.类的类名
# 2.类的继承,python3中默认继承object
# 3.类必须要有自己的名称空间,里面定义了自己的数据属性和函数属性
class_name = 'Chinese'
class_bases = (object, )
class_body = """
country = 'China'
def __init__(self,name,age):
self.name = name
self.age = age
def talk(self):
print('%s is taking'%self.name)
"""
class_dic = {}
exec(class_body, globals(), class_dic)
Chinese = type(class_name, class_bases, class_dic)
print(class_dic)
【28.自定义元类控制类的创建】
如何自己定制元类来控制class的行为
# # 自定义元类最好指定type,因为你只是重写一部分类的方法,本身更多的类的属性还是从type中来的
#
#
# class Mymeta(type):
# def __init__(self,class_name, class_bases, class_dic):
# if not class_name.istitle():
# raise TypeError('类型错误,类名的首字母必须大写')
# super(Mymeta,self).__init__(class_name,class_bases,class_dic)
#
#
# class Chinese(object, metaclass=Mymeta):
# country = 'China'
#
# def __init__(self,name, age):
# self.name = name
# self.age = age
#
# def talk(self):
# print('%s is talking' % self.name)
# # Chinese = Mymeta(class_name,class_bases,class_dic)
class Foo:
'''
注释
'''
pass
print(Foo.__dict__)
print(Foo.__doc__)
【29.自定义元类控制类的实例化行为】
补充知识点:调用方法__call__
对象实例化以后调用__call__
1.先造一个空对象(object.__new__(self))
2.初始化(self.__init__(obj,*args,**kwargs))
3.返回(return obj)
# class Foo:
# def __call__(self, *args, **kwargs):
# print(self)
# print(args)
# print(kwargs)
#
#
# obj = Foo()
# obj(1,1,3,a=1,b=2)
# 调用对象实际上会触发__call__这个内置方法,不同的值会存成不同的形式保存
# 元类内部也是有一个__call__方法,会在调用Foo时触发执行
# Foo(1,2,x=1) Foo.__call__(Foo,1,2,x=1)
class Mymeta(type):
def __init__(self,class_name, class_bases, class_dic):
if not class_name.istitle():
raise TypeError('类型错误,类名的首字母必须大写')
if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
raise TypeError('必须有注释,且注释不能为空')
super(Mymeta,self).__init__(class_name,class_bases,class_dic)
def __call__(self, *args, **kwargs):
print('>>>>')
class Chinese(object, metaclass=Mymeta):
'''
注释
'''
country = 'China'
def __init__(self,name, age):
self.name = name
self.age = age
def talk(self):
print('%s is talking' % self.name)
# # Chinese = Mymeta(class_name,class_bases,class_dic)
obj = Chinese('panda', 20) # 实际上就是执行Chinese.__call__(Chinese,'panda',20)
【30.自定义元类控制类的实例化行为的应用】
#单例模式:默认参数一样的情况下,就不会生成新的内存空间了,用公用的就行(实际就是一种优化的策略)
#单例模式:默认参数一样的情况下,就不会生成新的内存空间了,用公用的就行(实际就是一种优化的策略)
class MySQL:
__instance = None
def __init__(self):
self.host = '127.0.0.1'
self.port = 3306
@classmethod
def singleton(cls):
if not cls.__instance:
obj = cls()
cls.__instance = obj
return cls.__instance
def find(self):
pass
def update(self):
pass
obj1 = MySQL.singleton()
obj2 = MySQL.singleton()
print(id(obj1))
print(id(obj2))
# #单例模式:默认参数一样的情况下,就不会生成新的内存空间了,用公用的就行(实际就是一种优化的策略)
# class MySQL:
# __instance = None
# def __init__(self):
# self.host = '127.0.0.1'
# self.port = 3306
# @classmethod
# def singleton(cls):
# if not cls.__instance:
# obj = cls()
# cls.__instance = obj
# return cls.__instance
#
# def find(self):
# pass
#
# def update(self):
# pass
#
#
# obj1 = MySQL.singleton()
# obj2 = MySQL.singleton()
#
# print(id(obj1))
# print(id(obj2))
# ---------------------------------------#
# 实现方式二:元类的方式
class Mymeta(type):
def __init__(self,class_name, class_bases, class_dic):
if not class_name.istitle():
raise TypeError('类型错误,类名的首字母必须大写')
super(Mymeta,self).__init__(class_name,class_bases,class_dic)
self.__instance=None
def __call__(self, *args, **kwargs):
if not self.__instance:
obj = object.__new__(self)
self.__init__(obj)
self.__instance = obj
return self.__instance
class Mysql(object,metaclass=Mymeta):
def __init__(self):
self.host = '127.0.0.1'
self.port = 3306
def find(self):
pass
def update(self):
pass
obj1 = Mysql()
obj2 = Mysql()
obj3 = Mysql()
print(id(obj1))
print(id(obj2))
print(id(obj3))
【31.面向对象的软件开发与作业介绍】
【32.什么是异常处理】
【32.try...except...详细方法】