第二十七章 更多实例

时间:2022-12-13 20:02:06
#1.
#A:类的__str__方法:每次一个实例转换为其打印字符串的时候,此函数会自动调用
#B:类的__repr__方法:提供对象的一种代码低层级显示
class CTest:
def __init__(self):
self.value = 10
def __str__(self):
return "str:%s" % self.value
def __repr__(self):
return "repr:%s" % self.value

Test = CTest()
str0 = str(Test) #str0 = 'str:10'
str1 = repr(Test) #str1 = 'repr:10'

#2.
#A:编写代码的时候存在一个很常见的问题:任何时候,当需要复制一段代码,基本上都会使得未来的维护工作倍增
#B:一种功能代码只出现在一个地方,将来需要修改的时候,我们就只需要进行一处修改,这对于代码维护意义重大

#3.
#A:类方法总是可以在一个实例中调用(通常python自动把该实例传递给self参数),或者通过类来调用(必须手动传递实例)
# instance.method(args) 等价于 class.methon(instance, args)
#B:多态是python灵活性的核心:根据传递的对象的类型,自动调用相应的版本
class CFather:
def __init__(self):
self.str = 'Father'
def GetStr(self):
return self.str

class CChild(CFather):
def __init__(self):
CFather.__init__(self)
self.str1 = 'Child'
def GetStr(self):
return CFather.GetStr(self) + " " + self.str1

Child = CChild()
str0 = Child.GetStr() #str0 = 'Father Child'
Father = CFather()
str1 = Father.GetStr() #str1 = 'Father'
str2 = CFather.GetStr(Father) #str2 = 'Father'

#4.
#A:若子类定义了__init__函数,并且子类想获得父类的属性,则子类必须调用父类的__init__函数
class CFather:
def __init__(self):
self.value = 'Father'
class CChild0(CFather):
pass
class CChild1(CFather):
def __init__(self):
pass
class CChild2(CFather):
def __init__(self):
CFather.__init__(self)

#注意点:在类方法中对于self的赋值将为类实例添加对应属性,而不会为类添加对应属性
#类的属性会自动添加给类实例
bValue0 = 'value' in dir(CFather()) #bValue0 = True
bValue1 = 'value' in dir(CFather) #bValue1 = False

bValue2 = 'value' in dir(CChild0()) #bValue2 = True
bValue3 = 'value' in dir(CChild1()) #bValue3 = False
bValue4 = 'value' in dir(CChild2()) #bValue4 = True

#5.
#A:instance.__class__属性提供了一个从实例到创建她的类的链接
#B:类反过来有一个__name__来得到类名
#C:__bases__:列出基类名称
#D:__dict__:提供了属性的列表
class CFather:
def __init__(self):
self.value = 'Father'
class CChild(CFather) : pass
Father = CFather() #Father = <__main__.CFather object at 0x0000000002D595F8>
v0 = Father.__class__ #v0 = <class '__main__.CFather'>
v1 = Father.__class__.__name__ #v1 = 'CFather'
v2 = Father.__class__() #v2 = <__main__.CFather object at 0x0000000002D54CF8>
str0 = v2.value #str0 = 'Father'
str1 = CFather.__name__ #str1 = 'CFather'
v3 = CChild.__bases__ #v3 = (<class '__main__.CFather'>,)
str2 = v3[0]().value #str2 = 'Father'
dict0 = CFather.__dict__
'''
dict0 = mappingproxy({'__module__': '__main__', '__dict__': <attribute '__dict__' of 'CFather' objects>,
'__doc__': None, '__weakref__': <attribute '__weakref__' of 'CFather' objects>,
'__init__': <function CFather.__init__ at 0x0000000002E140D0>})
'''
dict1 = Father.__dict__ #dict1 = {'value': 'Father'}
dict2 = CChild().__dict__ #dict2 = {'value': 'Father'}

#6.
#A:类和类实例的__dict__:类实例的__dict__只会得到对self的顶层赋值的属性,而类的__dict__属性会得到类定义中的顶层赋值属性,不包括对self赋值的属性
#B:可以用dir内置函数获取全部属性
class CFather():
valueFather = 'Father'
def __init__(self):
#self.value1 = valueFather #报错
self.value1 = CFather.valueFather

class CChild(CFather):
def __init__(self):
CFather.__init__(self)
self.value2 = 'Child'

Father = CFather()
Child = CChild()

str0 = Father.__dict__ #str0 = {'value1': 'Father'}
str1 = Child.__dict__ #str1 = {'value1': 'Father', 'value2': 'Child'}

b0 = 'valueFather' in CFather.__dict__ #b0 = True
b1 = 'value1' in CFather.__dict__ #b1 = False

bValue0 = 'value1' in dir(Father) #bValue0 = True
bValue1 = 'valueFather' in dir(Father) #bValue1 = True

#7.
#A:pickle模块是一种非常通用的对象格式化和解格式化工具:对于内存中的任何python对象,都能转化为字符串,这个字符串随后能用于重建python对象
#B:shelve模块提供了一个额外的层结构,允许按照键来存储pickle处理后的对象
import pickle
'''
pickle英[ˈpɪkl]
美[ˈpɪkəl]
vt.腌渍(泡菜等)
'''
list0 = {'a':1, 'b':2}
file = open('Test.pkl', "wb")
pickle.dump(list0, file)
file.close()

file = open("Test.pkl", "rb")
list1 = pickle.load(file) #list1 = {'a': 1, 'b': 2}
file.close()

class CTest():
def __init__(self):
self.value0 = 'value0'
self.value1 = 'value1'
Test = CTest()
file = open('Test.pkl', "wb")
pickle.dump(Test, file)
file.close()

file = open("Test.pkl", "rb")
Test1 = pickle.load(file)
value = Test1.value0, Test1.value1 #value = ('value0', 'value1')
file.close()

import shelve
'''
shelve英[ʃelv]
美[ʃɛlv]
vt.将(书等)放置在架子上; 将…搁在一边; 装搁架于; 罢免;
vi.(陆地) 逐渐倾斜
'''
list0 = [CTest(), CTest()]
list0[0].value0 = '0'
list0[1].value0 = '1'

db = shelve.open("Test")
#为了载入和使用存储的对象,我们不一定要导入所存储的类,其内部会使用pickle操作来记录self属性,当随后从shelve获取属性的时候,会自动重新载入该类
#上述特性导致了:随后载入一个实例的时候,类及其模块文件都必须被导入,这个模块文件可以通过sys.path所查找
# 当该类的实例再次载入的时候,对类文件的源代码的修改会自动生效

for v in list0:
db[v.value0] = v
db.close()

db = shelve.open("Test")
value = len(db) #value = 2
str0 = db['0'].value0 #str0 = '0'
str1 = db['1'].value0 #str1 = '1'
db.close()