python_day8

一:魔法方法

1.__str__()

>>> class A():
    def __str__(self):
        return "小甲鱼是帅哥"

    
>>> a=A()
>>> print(a)
小甲鱼是帅哥
View Code

2.__repr__()

>>> class B():
    def __repr__(self):
        return "小甲鱼是帅哥"

    
>>> b=B()
>>> b
小甲鱼是帅哥
View Code

3.简单定制:
基本要求:

定制一个计时器类
start和stop方法代表启动计时和停止计时
假设计时器对象t1,print(t1)和直接调用t1均显示结果
当计时器未启动或已经停止计时,调用stop方法会给予温馨提示
两个计时器对象可以进行相加:t1+t2
只能使用提供有限资源完成

import time as t

class MyTime():
    def __init__(self):   #进行变量和函数的初始化
        self.unit=['','','','','','']  #时间单位
        self.prompt='未开始计时' #提示语句
        self.lasted=[]  #持续时间存储的列表
        self.begin=0    #开始时间初始化
        self.end=0  #结束时间初始化
    def __str__(self):  #调用实例直接显示结果
        return self.prompt
    def __repr__(self):
        return self.prompt
    def __add__(self, other):
        prompt='总共运行了'
        result=[]
        for index in range(6):
            result.append(self.lasted[index]+other.lasted[index])
            if result[index]:
                prompt+=(str(result[index])+self.unit[index])
        return  prompt

    #开始计时
    def start(self):
        self.begin=t.localtime()
        self.prompt='提示:请先调用stop停止计时'
        print('计时开始..')

    #内部方法,计算运行时间
    def _calc(self):
        self.lasted=[]
        self.prompt='总共运行了'
        for index in range(6):#只要前六位返回的结果
            self.lasted.append(self.end[index]-self.begin[index])
            if self.lasted[index]:
                self.prompt+=(str(self.lasted[index])+self.unit[index])
        self.begin=0
        self.end=0
        print(self.prompt)
    #停止计时
    def stop(self):
        if not self.begin:
            print('提示:请先调用start()进行计时')
        else:
            self.end=t.localtime()
            self._calc()
            print('计时结束!')

t1=MyTime()
t2=MyTime()
t1.start()
t.sleep(45)
t1.stop()
t2.start()
t.sleep(15)
t2.stop()
print(t1+t2)
View Code


使用time模块的localtime方法获取时间。time.localtime返回struct_time的时间格式:
包括:tm_year 年
月 tm_mon
日 tm_mday
时 tm_hour
分 tm_min
秒tm_sec
weekday:0-6 0表示周日 tm_wday
一年中的第几天1-366  tm_yday
是否是夏令时    tm_isdst

4.属性访问

用__getattr__()魔法方法

>>> c=C()
>>> c.x
'X_man'
>>> getattr(c,'x','没有这个属性')
'X_man'
>>> getattr(c,'y','没有这个属性')
'没有这个属性'
View Code

用property

>>> class C:
    def __init_(self,size=10):
        self.size=size
    def getSize(self):
        return self.size
    def setSize(self,value):
        self.size=value
    def delSize(self):
        del self.size
    x=property(getSize,setSize,delSize)

    
>>> c=C()
>>> c.x=1
>>> c.x
1
>>> del c.x
>>> c.size
Traceback (most recent call last):
  File "<pyshell#42>", line 1, in <module>
    c.size
AttributeError: 'C' object has no attribute 'size'
View Code

5.几个魔法方法:
__getattr__(self,name)
定义当用户试图获取一个不存在的属性时的行为
__getattribute__(self,name)
定义当该类的属性被访问时的行为
__setattr__(self,name,value)
定义当一个属性被设置时的行为
__delattr__(self,name)
定义当一个属性被删除时的行为

>>> class C:
    def __getattribute__(self,name):
        print('getttribute')
        return super().__getattribute__(name)
    def __getattr__(self,name):
        print('getattr')
    def __setattr__(self,name,value):
        print('setattr')
        super().__setattr__(name,value)
    def __delattr__(self,name):
        print('delattr')
        super().__delattr__(name)

        
>>> c=C()
>>> c.x
getttribute
getattr
>>> c.x=1
setattr
>>> c.x
getttribute
1
>>> del c.x
delattr 
View Code

练习:
写一个矩形类,默认有宽和高两个属性。如果为一个叫square的属性赋值,那么说明这是一个正方形,值就是正方形的边长,此时宽和高都等于边长。

>>> class Rectangle:
    def __init__(self,width=0,height=0):
        self.width=width
        self.height=height  #当这两个属性被定义时,调用__setattr__()
    def __setattr__(self,name,value):#重写魔法方法
        if name=='square':
            self.width=value
            self.height=value
        else:
            super().__setattr__(name,value) #调用基类的__setattr__方法
    def getArea(self):
        return self.width*self.height

    
>>> r=Rectangle()
>>> r1=Rectangle(4,5)
>>> r1.getArea()
20
>>> r1.square=10
>>> r1.height
10
>>> r1.width
10
>>> r1.getArea()
100
View Code

二:描述符

描述符(Property的原理):描述符就是将某种特殊类型的类(含有以下三个魔方的一个或多个)的实例指派给另一个类的属性。
__get__(self,instance,owner)
用于访问属性,它返回属性的值
__set__(self,instance,value)
将在属性分配操作中调用,不返回任何内容
__delete__(self,inatance)
控制删除操作,不返回任何内容

>>> class MyDecriptor:
    def __get__(self,instance,owner):
        print('getting...',self,instance,owner)
    def __set__(self,instance,value):
        print('setting',self,instance,value)
    def __delete__(self,instance):
        print('deleting',self,instance)

        
>>> class Test:
    x=MyDecriptor()

    
>>> test=Test()
>>> test.x
getting... <__main__.MyDecriptor object at 0x00357C50> <__main__.Test object at 0x00357FB0> <class '__main__.Test'>
>>> test
<__main__.Test object at 0x00357FB0>
>>> Test
<class '__main__.Test'>
>>> test.x='X_man'
setting <__main__.MyDecriptor object at 0x00357C50> <__main__.Test object at 0x00357FB0> X_man
>>> del test.x
deleting <__main__.MyDecriptor object at 0x00357C50> <__main__.Test object at 0x00357FB0>
View Code

① self: MyDecriptor的实例对象,其实就是Test的属性x
② instance: Test的实例对象,其实就是test
③ owner: 即谁拥有这些东西,当然是 Test 这个类,它是最高统治者,其他的一些都是包含在它的内部或者由它生出来的
可以利用这个重写Property
2.练习:

先定义一个温度类,然后定义两个描述符用于描述摄氏度和华氏度两个属性。要求两个属性会自动进行转换,也就是说你可以给摄氏度这个属性赋值,然后打印的华氏度属性是自动转换后的结果。

>>> class Celsius:
    def __init__(self,value=26.0):
        self.value=float(value)
    def __get__(self,instance,owner):
        return self.value
    def __set__(self,instance,value):
        self.value=float(value)

    
>>> class Fahrenheit:
    def __get_(self,instance,owner):
        return instance.cel*1.8+32
    def __set__(self,instance,value):
        instance.cel=(float(value)-32)/1.8

        
>>> class Temperature:
    cel=Celsius()
    fah=Fahrenheit()

    
>>> temp=Temperature()
>>> temp.cle
Traceback (most recent call last):
  File "<pyshell#125>", line 1, in <module>
    temp.cle
AttributeError: 'Temperature' object has no attribute 'cle'
>>> temp.cel
26.0
>>> temp.fah=100
>>> temp.cel
37.77777777777778
View Code

三:练习

定制序列:
 编写一个不可改变的自定义列表,要求记录列表中每个元素被访问的次数

>>> class CountList:
    def __init__(self,*args):
        self.values=[x for x in args]
        self.count={}.fromkeys(range(len(self.values)),0)
    def __len__(self):
        return len(self.value)
    def __getitem__(self,key):
        self.count[key]+=1
        return self.values[key]

    
>>> c1=CountList(1,3,5,7,9)
>>> c2=CountList(2,4,6,8,10)
>>> c1[1]
3
>>> c2[1]
4
>>> c1[1]+c2[1]
7
>>> c1.count
{0: 0, 1: 2, 2: 0, 3: 0, 4: 0}
View Code

 四:迭代器
两个BIF:iter()    next()

>>> string='fishc'
>>> it=iter(string)
>>> next(it)
'f'
>>> next(it)
'i'
>>> next(it)
's'
>>> next(it)
'h'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
  File "<pyshell#160>", line 1, in <module>
    next(it)
StopIteration
View Code
>>> string='fishc'
>>> it=iter(string)
>>> while True:
    try:
        each=next(it)
    except StopIteration:
        break
    print(each)

    
f
i
s
h
c
View Code

魔法方法:__iter__()       __next__()

>>> class Fibs:
    def __init__(self):
        self.a=0
        self.b=1
    def __iter__(self):
        return self
    def __next__(self):
        self.a,self.b=self.b,self.a+self.b
        return self.a

    
>>> fibs=Fibs()
>>> for each in fibs:
    if each<30:
        print(each)
    else:
        break

    
1
1
2
3
5
8
13
21
View Code

五:生成器

生成器:生成器就像一个特殊的迭代器

>>> def myGen():
    print('生成器被执行')
    yield(1)
    yield(2)

    
>>> myG=myGen()
>>> next(myG)
生成器被执行
1
>>> next(myG)
2
>>> next(myG)
Traceback (most recent call last):
  File "<pyshell#203>", line 1, in <module>
    next(myG)
StopIteration
View Code

生成器,斐波拉契数列

>>> def libs():
    a=0
    b=1
    while True:
        a,b=b,a+b
        yield a

        
>>> for each in libs():
    if each >100:
        break
    print(each,end=' ')

    
1 1 2 3 5 8 13 21 34 55 89 
View Code

 


 

 

 

 

 

 

 

 

 

 



posted @ 2019-04-16 10:44  wwq1204  阅读(156)  评论(0编辑  收藏  举报