面向对象进阶
Posted ghylpb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象进阶相关的知识,希望对你有一定的参考价值。
目录
面向对象进阶
Wisdom is knowing what to do next , virtue is doing it .
classmethod 和 staticmethod
classmethod
装饰给类内部的方法,使该方法绑定给类使用。由类调用,将类作为第一个参数传入方法,不影响对象对该方法的调用。
class People:
def __init__(self,name,age):
self.name = name
self.age = age
print(self)
@classmethod
def tell_info(cls):
print(cls)#这里只是说明这个方法已经绑定给了类,所以其参数是类
print('此处是类方法。。。')
p = People('tank',18)
p.tell_info()
#<__main__.People object at 0x00000272647D8A20>
# <class '__main__.People'>
# 此处是类方法。。。
staticmethod
是一个装饰器,可以装饰给类内部的方法,使该方法不绑定给对象,也不绑定给类使其变成一个普通的函数,但是不改变其调用方式。(__class__对象的属性,获取当前对象的类)
小练习
1、定义mysql类
1.对象有id、host、port三个属性
2.定义工具create_id,在实例化时为每个对象随机生成id,保证id唯一
3.提供两种实例化方式,方式一:用户传入host和port 方式二:从配置文件中读取host和port进行实例化
#下面代码仅给出了实例化的两种方式,和ID的产生
import hashlib,uuid,settings#settings为配置文件(配置文件其实就是一个自定义的模块)
class Teacher:
def __init__(self,user,pwd):#通过对象的绑定方法产生一个对象(对象名 = 类(参数))
self.user = user
self.pwd = pwd
def index(self):
if self.user == 'tahk' and self.pwd == '123':
print('验证通过,显示主页。。。')
@classmethod
def login_auth_from_settings(cls):#通过配置文件的方式产生一个对象(通过类的绑定方法产生一个对象)
obj = cls(settings.USER,settings.PWD)
return obj
@staticmethod
def create_id():
uuid_obj = uuid.uuid4()
md5 = hashlib.md5()
md5.update(str(uuid_obj).encode('utf8'))
return md5.hexdigest()
obj = Teacher.login_auth_from_settings()#通过配置文件产生对象需要单独调用实例化方法
obj.index()
tea1 = Teacher('tank', '123')
print(tea1.create_id())
tea1.index()
print(Teacher.create_id())
isinstance 和 issubclass
isinstance
isinstance******(参数1,参数2)返回bool值判断参数1(对象)是否是参数二(类)的实例。
issubclass
issubclass*****判断参数一(子类)是否是参数二(父类)的子类反射*******指通过字符串对对象或类的属性进行操作。
class Foo:
pass
class Goo(Foo):
pass
foo_obj = Foo()
print(isinstance(foo_obj, Foo))
print(isinstance(foo_obj, Goo)) # False
print(issubclass(Goo, Foo)) # True
反射
反射指通过字符串对对象或类的属性进行操作。
hasattr:通过判断该字符串是否是对象或类的属性。
getattr:通过字符串获取对象或类的属性。
setattr:通过字符串设置对象或类的属性,如果属性不存在会为对象添加属性。
delattr:通过字符串删除对象或类的属性。
class People:#创建一个类
country = 'China'
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
p = People('tank',17,'male')
#普通方式
print('name' in p.__dict__)#判断name是否是对象的属性值
#hasattr
print(hasattr(p,'name'))
print(hasattr(People,'country'))
#获取属性值
#普通方式
print(p.__dict__.get('name'))
#getattr
print(getattr(p,'name','jason_sb'))#如果有值则返回属性值,如果没有则返回最右侧的这个值
print(getattr(People,'country2','China'))
#为对象或类添加属性
#普通方式
p.level = 10
print(p.level)
#setattr
setattr(p,'sal','3.0')
print(hasattr(p,'sal'))
#删除对象的属性
#普通方式
del p.level
print(hasattr(p,'level'))
#delattr
delattr(p,'sal')
print(hasattr(p,'asl'))
print(p.__dict__.get('level'))
反射小练习:使用反射实现输入属性的名字就可以执行类或对象中的方法。
class Movie:
def input_cmd(self):
print('输入命令:')
while True:
cmd = input('请输入方法名').strip()
if hasattr(self,cmd):
method = getattr(self,cmd)
method()
def upload(self):
print('电影开始上传')
def download(self):
print('电影开始下载')
movie_obj = Movie()
movie_obj.input_cmd()
魔法方法
魔法方法(类的内置方法):凡是在类内部定义,以__开头__结尾都称之为魔法方法,又称类的内置方法,
会在某些条件成立的情况下触发。
__init__:在调用类时触发。
__str__:会在打印对象时触发,必须要return一个字符串类型的值。
__str__应用:打印一个列表等等。
__del__:会在程序执行结束时触发,对象销毁,该方法会在最后被执行和其定义的位置无关。
__getattr__:会在对象.属性时,属性没有的情况下触发,如果没有默认返回None,我们可以加return 我们想要的值。
__setattr__:会在对象.属性 = 属性值 时触发,出发时外部的对象添加属性赋值就没用了,属性赋值在内部进行。
__call__:会在对象被调用时触发。
__new__:会在__init__执行前触发,真正的实例化对象就是通过object类中的__new__进行的,__new__会创建一个空的实例化对象。
class Foo(object):
def __new__(cls, *args, **kwargs):
print(cls)
return object.__new__(cls)#通过object产生一个空对象
def __init__(self):
print('在调用类时触发。。。')
def __str__(self):
print('在打印时触发。。。')
return 'xiaohua'
def __del__(self):
print('对象被销毁前执行该方法')
def __getattr__(self, item):
print('会在对象.属性时,属性没有的情况下触发')
print(item)
#默认返回None,若想打印属性的结果,必须return一个值
return 1
def __setattr__(self, key, value):
print('会在对象.属性 = 属性值 时触发...')
print(key,value)
print(type(self))
print(self,111)
self.__dict__[key] = value
def __call__(self, *args, **kwargs):
print(self)
print('调用对象时触发该方法...')
foo_obj = Foo()
print(foo_obj.__class__)
foo_obj.x = 10
#print(foo_obj.x)
print(foo_obj)
小练习:使用魔法方法和open,实现with open的功能。
class MyFile:
def __init__(self,file_name,mode = 'r',encoding = 'utf8'):
self.file_name = file_name
self.mode = mode
self.encoding = encoding
def file_open(self):
self.f = open(self.file_name,self.mode,encoding=self.encoding )
def file_read(self):
res = self.f.read()
print(f'''
当前文件名称:{self.file_name}
当前文件数据:{res}
''')
def __del__(self):
self.f.close()
print('文件关闭成功')
f = MyFile('biji.txt')
f.file_open()
f.file_read()
单例模式
单例模式指的是单个实例,实例指的时调用类产生的对象。
? 实例化多个对象会产生不同的内存地址,单例可以让所有调用者, 在调用类产生对象的情况下都指向同一份内存地址。 例如: 打开文件。
? 单例的目的:
? 为了减少内存的占用。
class File:
__instance = None
# 单例方式1
@classmethod
def singleton(cls,file_name):
if not cls.__instance:
obj = cls(file_name)
cls.__instance = obj
return cls.__instance
def __init__(self,file_name,mode='r',encoding = 'utf8'):
self.file_name = file_name
self.mode = mode
self.encoding = encoding
def open(self):
self.f = open(self.file_name,self.mode,encoding=self.encoding)
def read(self):
res = self.f.read()
print(res)
def close(self):
self.f.close()
file1 = File.singleton('biji.txt')#此处必须要调用这个方法才行
print(file1)
file2 = File.singleton('biji.txt')
print(file2)
class File:
__instance = None
# 单例方式2
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
def __init__(self,file_name,mode='r',encoding = 'utf8'):
self.file_name = file_name
self.mode = mode
self.encoding = encoding
def open(self):
self.f = open(self.file_name,self.mode,encoding=self.encoding)
def read(self):
res = self.f.read()
print(res)
def close(self):
self.f.close()
file1 = File('biji.txt')#此处必须要调用这个方法才行
print(file1)
file2 = File('biji.txt')
print(file2)
以上是关于面向对象进阶的主要内容,如果未能解决你的问题,请参考以下文章