面向对象编程(四)
一、面向对象的魔法方法
1.魔法方法简介
在类中,有一些内置好的特定的方法,方法名是“__xx__”,在进行特定的操作时会被调用,这些方法被称为魔法方法,不需要人为调用 在特定的条件下回自动触发运行
2.常见的魔法方法即代码实现
'''__init__ : 实例化对象的时候自动触发,初始化一个类,在创建实例对象为其赋值'''
class Person(object):
def __init__(self):
print('__init__方法')
obj = Person()
'''__call__ : 当对象加括号调用时自动触发该方法'''
class Person(object):
def __call__(self, *args, **kwargs):
print('__call__方法')
print(args)
print(kwargs)
obj = Person()
print(obj.__call__())
'''__str__ : 对象被执行打印操作的时候会自动触发,该方法必须返回一个字符串'''
class Person(object):
def __str__(self):
return '这是类:%s 产生的一个对象'%self.name
obj = Person()
print(obj.__str__())
'''__getattr__ : 当对象获取的属性名不存在时触发,返回获取的这个不存在的属性名'''
class Person(object):
def __getattr__(self, item):
print('__getattr__', item)
return '您想要获取的属性名:%s不存在'%item
obj = Person()
print(obj.__getattr__('age'))
'''__setattr__ : 对象操作属性值的时候自动触发'''
class Person(object):
def __setattr__(self, key, value):
print(key)
print(value)
obj = Person()
print(obj.__setattr__('name','age'))
'''__del__ : 对象在被主动或被动删除的时候自动触发'''
class Person(object):
def __init__(self,name):
self.name = name
def __del__(self):
print('触发啦')
obj = Person('把我删啦')
print(obj.__del__())
'''__getattribute__ :对象在获取属性的时候自动触发 不管这个属性是否存在
(当一个类中既有__getattr__又有__getattribute__时只走后者)'''
class Person(object):
def __init__(self,name):
self.name = name
def __getattribute__(self, item):
return super(Person, self).__getattribute__(item) # 复杂写法
return super().__getattribute__(item) # 简便写法
obj = Person('把我删啦')
print(obj.__getattribute__('name'))
'''__exit__ :对象被with语法执行并运行完with子代码之后自动触发
def __exit__(self, exc_type, exc_val, exc_tb):对象被with语法执行并运行完with子代
码之后 自动触发'''
class Open:
def __init__(self,name):
self.name=name
def __enter__(self):
print('对象被with语法执行的时候自动触发 该方法返回什么 as关键字后面的变量名就能得到什么')
def __exit__(self, exc_type, exc_val, exc_tb):
print('对象被with语法执行并运行完with子代码之后 自动触发')
with Open('a.txt') as f:
print(f)
3.魔法方法笔试题
1.补全下列代码使得不报错
class Context:
pass
with Context() as f:
f.do_something()
class Context:
def do_something(self):
pass
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
pass
with Context() as f:
f.do_something()
2.自定义字典类型并让字典能够通过句点符的方式操作键值对
class MyDict(dict):
def __setattr__(self, key, value):
self[key] = value
def __getattr__(self, item):
return self.get(item)
obj = MyDict()
obj.name = 'jason'
obj.pwd = 18
obj.hobby = 'read'
# print(obj)
print(obj.name)
print(obj.pwd)
print(obj.hobby)
# print(obj)
# print(obj) # 字典存储的数据 {}
# print(obj.__dict__) # 字典对象名称空间 {'name': 'jason'}
print(type(obj))
二、元类简介
所有的对象都是实例化或者通过调用类得到的,python中一切皆对象,通过class关键字定义的类本质也是对象,对象又是通过调用类得到的,因此通过class关键字定义的类肯定也是调用了一个类得到的,这个类就是元类。
"""结论:我们定义的类其实都是由type类产生的>>>:元类(产生类的类)"""
三、创建类的两种方式
1.使用关键字class
class Teacher:
school_name = '芜湖大学'
def func1(self):
pass
print(Teacher)
print(Teacher.__dict__)
# <class '__main__.Teacher'>
{'__module__': '__main__', 'school_name': '芜湖大学', 'func1': <function Teacher.func1 at 0x00000213C5AD7790>, '__dict__': <attribute '__dict__' of 'Teacher' objects>, '__weakref__': <attribute '__weakref__' of 'Teacher' objects>, '__doc__': None}
2.利用元类type type(类名,类的父类,类的名称空间)
cls = type('Student', (object,), {'name':'jason'})
print(cls)
print(cls.__dict__)
# <class '__main__.Student'>
{'name': 'jason', '__module__': '__main__', '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
四、元类定制类的产生行为
# 1.自定义元类:继承type的类也称之为元类
class MyMetaClass(type):
def __init__(self, what, bases=None, dict=None):
# print('what', what)
# print('bases', bases)
# print('dict', dict)
if not what.istitle():
raise TypeError('类名首字母应该大写啊!!!')
super().__init__(what, bases, dict)
# 2.指定类的元类:利用关键字metaclass指定类的元类
class myclass(metaclass=MyMetaClass):
desc = '元类其实很有趣 '
class Student(metaclass=MyMetaClass):
info = '我很听话'
print(Student)
print(Student.__dict__)
五、元类定制对象的产生行为
class MyMetaClass(type):
def __call__(self, *args, **kwargs):
# 1.产生一个空对象(骨架)
# 2.调用__init__给对象添加独有的数据(血肉)
# 3.返回创建好的对象
# print(args) # ('jason', 18, 'male')
# print(kwargs) # {}
if args:
raise TypeError("对象的独有数据必须按照关键字参数传参!!!")
return super().__call__(*args, **kwargs)
class Student(metaclass=MyMetaClass):
def __init__(self, name, age, gender):
# print('__init__')
self.name = name
self.age = age
self.gender = gender
# obj = Student('jason', 18, 'male')
obj = Student(name='jason',age= 18,gender= 'male')
print(obj.__dict__)
类中的__init__用于实力化对象
元类中的__init__用于实例化类
ps:只有继承了type的类才可以称之为是元类,如果想要切换产生类的元类不能使用继承需要使用关键字metaclass声明
ps:如果我们想控制对象的产生过程 可以操作元类里的__call__
如果我们想控制类里的产生过程 可以操作元类里的__init__
六、魔法方法之双下new方法
class Person(object):
def __init(self,*args,**kwargs):
print('init')
def __new__(cls,*args,**kwargs):
print('new')
print(type(cls))
obj = Person()
'''打印结果
new
<class 'type'>
'''
七、设计模式简介及单例模式
1.设计模式
前人通过大量的验证创建出来解决一些问题的固定高效方法
2.IT行业
23种
创建型
结构型
行为型
3.单例模式
类加括号无论执行多少次永远只会产生一个对象
目的:
当类中有很多非常强大的方法 我们在程序中很多地方都需要使用
如果不做单例 会产生很多无用的对象浪费存储空间
标签:__,obj,name,self,面向对象编程,print,def
From: https://www.cnblogs.com/zx0524/p/16870840.html