day27
2018-04-17 本文已影响2人
两分与桥
isinstance(t, son) 检测 t 是否是 son 的实例
issubclass(son, Earth) 检测 son 是否是 Earth 的子类
class Earth:
pass
class son(Earth):
pass
t = son()
print(isinstance(t, son))
print(issubclass(son, Earth))
输出结果:
True
True
__getattribute__
属性,可以防止程序奔溃
class Earth:
def __init__(self, name):
self.name = name
def __getattr__(self, item):
print("getattr is work,get the ", item)
#不管调用什么属性都会触发 __getattribute__ 属性,存在 __getattribute__ 属性就不会触发 __getattr__ 属性
def __getattribute__(self, item):
print('getattribute is work, get the ', item)
raise AttributeError("抛出异常了") # 模拟抛出异常,防止程序奔溃,raise 触发 __getattr__
e = Earth('game')
e.name
e.none
输出结果:
getattribute is work, get the name #name 存在
getattr is work,get the name
getattribute is work, get the none #none 不存在
getattr is work,get the none
getitem,setitem,delitem,三个内置属性的使用方法
class Earth:
def __getitem__(self, item): #只有当特定方式 get 的时候才触发,就像 f['name']
print('getitem', item)
return self.__dict__[item]
def __setitem__(self, key, value): #
print('setitem %s %s '%(key,value))
self.__dict__[key] = value
def __delitem__(self, key):
print('delitem',key)
del self.__dict__[key]
f = Earth()
f.name = 'libai'
f.age = 20
print(f.__dict__)
f['call'] = 1833 #触发 setitem
print(f.__dict__)
print('----------------------------------------')
del f.name
print(f.__dict__)
del f['call'] #触发 delitem
print(f.__dict__)
print('----------------------------------------')
print(f['age']) #触发 getitem
print(f.__dict__['age'])
输出结果:
{'name': 'libai', 'age': 20}
setitem call 1833
{'name': 'libai', 'age': 20, 'call': 1833}
----------------------------------------
{'age': 20, 'call': 1833}
delitem call
{'age': 20}
----------------------------------------
getitem age
20
20
自定义 str ,控制返回,print() 函数触发的是系统 str 的执行
class test:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return '名字是 %s,年龄是 %s' %(self.name, self.age)
t = test('libai', 20)
print(t)
print('---------------------------------')
l = list('www.baidu.com')
print(type(l))
输出结果:
名字是 libai,年龄是 20
---------------------------------
<class 'list'>
自定制 repr 方法,当 repr 与 str 同时存在时,会执行 str 方法,当没有 str 时,执行 repr
print 调用的就是 str 方法,repr是交互式界面返回的值
class test:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return '名字是 %s,年龄是 %s' %(self.name, self.age)
def __repr__(self):
return "return repr"
t = test('libai', 20)
print(t)
输出结果:
名字是 libai,年龄是 20
自定制 format 方法,格式化输出
format_dict = {
'ymd' : '{0.year} {0.mon} {0.day}',
'y-m-d' : '{0.year}-{0.mon}-{0.day}',
'y:m:d' : '{0.year}:{0.mon}:{0.day}'
}
class Date:
def __init__(self, year, mon, day):
self.year = year
self.mon = mon
self.day = day
def __format__(self, format_spec):
print("my format, format_spec = '%s'" %format_spec)
if format_spec and format_spec in format_dict:
return format_dict[format_spec].format(self)
else:
return format_dict['ymd'].format(self)
d = Date(2018, 4, 18)
print('{0.year} {0.mon} {0.day}'.format(d)) #一般的格式化输出
print(format(d, 'none')) #自定义格式化输出
print(format(d, 'y-m-d'))
print(format(d, 'y:m:d'))
输出结果:
my format, format_spec = 'none'
2018 4 18
my format, format_spec = 'y-m-d'
2018-4-18
my format, format_spec = 'y:m:d'
2018:4:18
类实例化后都会建立一个各自的字典,公共的属性调用类的
class Date:
def __init__(self, name ,age):
self.name = name
self.age = age
x = 1
d1 = Date('libai', 20)
d2 = Date('baicai', 12)
print("d1.name = %s, id(d1.name) = %s " %(d1.name,id(d1.name)))
print("d1.age = %s, id(d1.age) = %s " %(d1.age,id(d1.age)))
print("d1.x = %s, id(d1.x) = %s " %(d1.x,id(d1.x))) #d1.x 的id 等于 d2.x 的id
print('-------------------------------------------')
print("d2.name = %s, id(d2.name) = %s " %(d2.name,id(d2.name)))
print("d2.age = %s, id(d2.age) = %s " %(d2.age,id(d2.age)))
print("d2.x = %s, id(d2.x) = %s " %(d2.x,id(d2.x)))
输出结果:
d1.name = libai, id(d1.name) = 1733015461592
d1.age = 20, id(d1.age) = 1989374016
d1.x = 1, id(d1.x) = 1989373408 #=================
-------------------------------------------
d2.name = baicai, id(d2.name) = 1733015480112
d2.age = 12, id(d2.age) = 1989373760
d2.x = 1, id(d2.x) = 1989373408 #=================
slots 属性可以优化内存(一般不会用到)
class earth: # 只能定义name 和 age 属性,优化内存
__slots__ = ['name', 'age']
d = earth()
print(d.__slots__)
d.name = 'libai'
d.age = 20
输出结果:
['name', 'age']
doc 属性不能继承
class earth:
'描述信息'
pass
class son(earth): # __doc__ 属性不能继承
pass
d = earth()
print(earth.__dict__)
print(son.__dict__)
print(d.__dict__)
输出结果:
{'__module__': '__main__', '__doc__': '描述信息', '__dict__': <attribute '__dict__' of 'earth' objects>, '__weakref__': <attribute '__weakref__' of 'earth' objects>}
{'__module__': '__main__', '__doc__': None}
{}
module 和 class 模块
module 查看在哪一个模块
class 查看是由哪个类产生的
# a 目录下的 test.py 文件
class C:
def __init__(self):
self.name = 'libai'
# 与 a 目录同级别的文件
from a.test import C
t = C()
print(t.name)
print(t.__module__)
print(t.__class__)
输出结果:
libai
a.test
<class 'a.test.C'>
析构函数 del,实例被系统回收时触发
class earth:
def __init__(self):
self.name = 'libai'
def __del__(self):
print('del is work')
e = earth()
print(e.name)
del e.name #不会触发 __del__ 函数
#程序结束时实例被系统回收,触发 __del__ 函数
输出结果:
libai
del is work
call 方法
class earth:
def __call__(self, *args, **kwargs):
print('call is work')
f= earth()
f() #调用类 earth 下的 __call__ 方法
迭代器,iter 和 next,
class Fib():
def __init__(self):
self.a = 1
self.b = 1
self.time = 0 #计算执行 __iter__ 次数
def __iter__(self): #把对象变成可迭代,可以看到,只调用一次迭代器 __iter__ 方法
self.time += 1
return self
def __next__(self):
self.a, self.b = self.b, self.a+self.b
if self.a > 20:
raise StopIteration('终止了')
return self.time,self.a
f = Fib()
print(next(f)) #只会向前,不会后退
print(next(f))
print(next(f))
print('==========================')
for i in f:
print(i)
print('==========================')
print(next(f))
输出结果:
(0, 1)
(0, 2)
(0, 3)
==========================
(1, 5)
(1, 8)
(1, 13)
========================== # 再次调用时引发 Stopiteration 异常
File "C:/PycharmProjects/begin/begin", line 12, in __next__
raise StopIteration('终止了')
StopIteration: 终止了
优先级
- 类属性
- 数据描述符
- 实例属性
- 非数据描述符
- 找不到的属性触发 getattr()
用pickle 序列化输入输出
#a.py 文件
import pickle
class earth:
pass
e = earth()
with open('a.txt', 'wb') as f:
pickle.dump(e, f)
# b.py 文件
import pickle
class earth:
pass
with open('a.txt', 'rb') as f:
pickle.load(f)
在 pycharm 中导入同个项目下的文件时 pycharm 会自动在环境变量中添加路径,但是一旦离开了 pycharm 就不能导入了,所以我们要手动添加可变环境变量
# 在 a 目录下的 test.py 文件中写了这个
def hello():
print('你好啊')
#与 a 目录同级别的目录
import sys, os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
sys.path.append(BASE_DIR)
print(os.path.dirname(__file__)) # os.path.dirname() 的作用就是返回到上级目录
print(os.path.dirname(os.path.dirname(__file__)))
print(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
from a import test
test.hello()
输出结果:
C:/Users/libai/PycharmProjects/begin
C:/Users/libai/PycharmProjects
C:/Users/libai
你好啊