Python基础之魔术方法(控制属性的访问和设置)

# 魔术方法--常规方法
# 1. __int__ 构造函数
# 2. __new__ 在类实例之前就创建了
# 3. __iter__ 迭代器
# 4. __del__ 析构方法,用来清除释放的对象内存
# 5. __class__ 魔术属性,返回所有的类--元类
# 6. __str__ 返回类+属性
# 7. __repr__ 返回类+属性,与__str__类似
# 8. __dict__ 返回类属性和对应的属性值,存储在字典中
# 9. dir() 返回当前类的属性和python内置属性,但不显示当前类属性的属性值

class Person(object):
def __new__(cls, *args, **kwargs):
return object.__new__(cls)

def __init__(self,name):
self.name = name
self.Address = 'SZ'

def __str__(self):
return 'Person<%s>'%self.name

def __repr__(self):
return 'Person<%s>'%self.Address


son = Person('MI')
P = Person('Oppo')
a = [son,P]
print(son)
print(a)
print(P.__dict__) # 返回{'name': 'Oppo', 'Address': 'SZ'}
print(dir(son)) # 返回当前对象的属性和系统Python的内置属性

# super的用法

# class A(object):
# def __init__(self,name):
# self.name = name
# print('HI:%s'%self.name)
#
# class B(A):
# def __init__(self,name):
# super(B, self).__init__(name)
# print('打印子类: %s'%self.name)
#
# b = B("Huawei")

'''
__getattr__魔术方法:
在访问一个对象的某个属性的时候,如果这个属性不存在,那么就会执行__getattr__方法,将属性的名字传进去。
如果这个属性存在,那么就不会调用__getattr__方法:
'''
class Person(object):
def __init__(self,name):
self.name = name

def __getattr__(self, attr):
# 注释: attr表示访问不存在的属性
if attr == 'age':
print('打印出__getattr__')
return self.name
else:
return None
p1 = Person('Teacher')
print(p1.name)
print("__getattr访问属性返回的值:{}".format(p1.age)) # 访问对象不存在的属性

'''
__setattr__
只要给一个对象的属性设置值,那么就会调用这个方法。
但是要注意的是,不要在这个方法中调用self.xxx=xxx的形式,因为会产生递归调用。
如果想要给对象的属性设置值,那么应该使用__dict__这个魔术属性。
'''

class Father(object):
def __init__(self,name,age):
self.name = name
self.age = age

def __setattr__(self, key, value):
print('打印出__setattr__')
self.__dict__[key] = value

fa = Father('Teache','20')
fa.name = "Tao"

'''
__getattribute__
这个魔术方法是,只要你访问了一个对象的属性,不管这个属性存不存在都会去执行这个方法,所以在写这个方法的时候要小心循环调用。
这个方法只能在新式类中使用,不能在旧时类中使用。
'''
class Mother(object):
def __init__(self,name,address):
self.name = name
self.address = address

def __getattribute__(self, attr):
print('===拦截住===')
if attr != 'name':
raise AttributeError

mon = Mother('Ha','SZ')
# mon.job # 访问的属性不是name时,抛出异常。


'''
__call__:可调用的对象
只要在创建类型的时候定义了__call__()方法,这个类型就是可调用的。
'''
class Reader(object):
count = 0
def __init__(self,name,nationality):
self.name = name
self.nationality = nationality
Reader.count += 1

def __call__(self, *args, **kwargs):
print('Reader is :%s'%self.name)
print('nationality is %s:'%self.nationality)
print('%s is being %s.' % (self.name, *args))
print('The total number of readers is %s.' % Reader.count)

a = Reader('Tony','China')
a('Bom')
# a(company='tom')
b = Reader('iris','China')
b('Jack')

'''
会话管理
__enter__
__exit__(self,exc_type,exc_val,exc_tb)魔术方法
执行完这个with语句中的代码块或者是这个代码块中的代码发生了异常,就会执行这个方法。可以在这个方法中做一些清理工作。比如关闭文件等。
如果在with语句中发生了异常,那么exc_type和exc_val将会存储这个异常的信息,如果没有任何异常,那么他们的值为None。
如果在with语句中发生了异常,那么会执行__exit__方法,但是如果你不想让这个异常抛出with代码块,那么你可以返回True,就不会把异常抛出到外面了。
'''

class FilePath(object):
def __init__(self,*args,**kwargs):
self.args = args
self.kwargs = kwargs

def __enter__(self):
self.fp = open(*self.args,**self.kwargs)
return self.fp

def __exit__(self, exc_type, exc_val, exc_tb):
self.fp.close()
print(exc_type)
return False

with FilePath('./login.txt','r') as fp:
a = 1
b = 0
# c = a/b
print(fp.read())

import json

data = {
'name':'Teacher',
'age':None
}
loads_dict = json.dumps(data)
print(type(loads_dict))
print(json.loads(loads_dict))
posted @ 2020-11-25 00:02  Test挖掘者  阅读(163)  评论(0编辑  收藏  举报