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

getitemsetitemdelitem,三个内置属性的使用方法

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}
{}

moduleclass 模块
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__ 方法

迭代器,iternext

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: 终止了

优先级

  1. 类属性
  2. 数据描述符
  3. 实例属性
  4. 非数据描述符
  5. 找不到的属性触发 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
你好啊
上一篇下一篇

猜你喜欢

热点阅读