代码改变世界

第二十七章 更多实例

2017-04-23 10:20  szn好色仙人  阅读(136)  评论(0编辑  收藏  举报
#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()