鱼C论坛

 找回密码
 立即注册

[技术交流] py3000愉快的开始

[复制链接]
 楼主| 发表于 2017-10-20 18:49:04 | 显示全部楼层

045魔法方法:属性访问(下)

本帖最后由 摆渡终极鉴黄师 于 2017-10-20 19:57 编辑

class Rectangle:
    def __init__(self, width=0, height=0):
        self.width = width
        self.height = height

    def __setattr__(self, name, value):
        if name == 'square':
            self.width = value
            self.height = value
        else:
            self.__dict__[name] = value

    def getArea(self):
        return self.width * self.height
(老湿:这名童鞋越来越偷懒了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-21 11:44:53 | 显示全部楼层

046魔法方法:描述符(Property的原理)(上)

本帖最后由 摆渡终极鉴黄师 于 2017-10-21 11:50 编辑

描述符就是将某种特殊类型的类的实例指派给另一个类的属性。
__get__(self, instance, owner)
-用于访问属性,Ta返回属性的值
__set__(self, instance, value)
-将在属性分配操作中调用,不返回任何内容
__delete__(self, instance)
-控制删除操作,不返回任何内容
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-22 12:05:58 | 显示全部楼层

046魔法方法:描述符(Property的原理)(中)

本帖最后由 摆渡终极鉴黄师 于 2017-10-22 13:53 编辑

class MyDescriptor:        #Descriptor其实就是一个描述符类
        def __get__(self, instance, owner):                #self就是描述符类的本身的一个实例,instance是Test的拥有者的类的实例,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 = MyDescriptor()                #括号是取这个类的实例,指派Test类的属性x,MyDescriptor是x的描述符,class Test:的上面的那一段代码就是描述符类
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-23 19:09:38 | 显示全部楼层

046魔法方法:描述符(Property的原理)(中2)

本帖最后由 摆渡终极鉴黄师 于 2017-10-23 19:35 编辑

class MyProperty:
        def __init__(self, fget=None, fset=None, fdel=None):
                self.fget = fget
                self.fset = fset
                self.fdel = fdel
               
        def __get__(self, instance, owner):
                return self.fget(instance)
       
        def __set__(self, instance, value):
                self.fset(instance, value)
               
        def __delete__(self, instance):
                self.fdel(instance)

class C:
        def __init__(self):
                self._x = None
               
        def getX(self):
                return self._x
       
        def setX(self, value):
                self._x = value
               
        def delX(self):
                del self._x
               
        x = MyProperty(getX, setX, delX)


>>> c = C()
>>> c.x = 'x-man'
>>> c.x
'x-man'
>>> c._x
'x-man'
>>>
这样就自己实现了一个property函数了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-24 16:31:40 | 显示全部楼层

046魔法方法:描述符(Property的原理)(下)

本帖最后由 摆渡终极鉴黄师 于 2017-10-24 17:21 编辑

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()#(笔记传送门——001,传送成功!)也就是在这里出现赋值了,fah这个属性有一个描述符类方法 Fahrenheit(),也就是说,Fahrenheit()这个描述符类,是描述这个fah属性的,当这个属性被赋值的时候,就会执行这个描述符类Fahrenheit的set方法,Ta事实上呢就是执行这个temp.cel(instance.cel)的等于号后面的那个计算后的值,然后存放到temp.cel里,temp.cel呢也是对这个temp的实例对象的cel属性进行赋值(也就是cel = Celsius()),Ta也有一个描述符类(也就是Celsius()),然后Ta就会执行到set里面去(Ceisius类里的set),最后设置到self.value里边去


>>> temp = Temperature()                #        实例化对象
>>> temp.cel                #        这是默认的,没有设置过的,如果你设置的话↓
26.0
>>> temp = Temperature(30)        #        这个类不行,这个类我们没有写Ta的init方法,init是在这个cel里边的,我们要设置的话呢要通过cel
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    temp = Temperature(30)
TypeError: object() takes no parameters
>>> temp.cel = 30                #        设置华氏度为30
>>> temp.fah
86.0                #        30*1.8+32 = 86度
>>> temp.fah = 100        #        现在设置华氏度为100,这个temp.fah = 100,也就是给Ta赋值(笔记传送门——001,开始传送中。。。。)
>>> temp.cel
37.77777777777778
>>>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-25 18:27:34 | 显示全部楼层

047魔法方法:定制序列(上)

本帖最后由 摆渡终极鉴黄师 于 2017-10-25 18:31 编辑

协议是什么?
·协议(Protocols)与其他编程语言中的接口很相似,Ta规定你那些方法必须要定义。然而,在Python中的协议就显得不那么正式。事实上,在Python中,协议更像是一种指南。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-26 18:49:37 | 显示全部楼层

047魔法方法:定制序列(中)

本帖最后由 摆渡终极鉴黄师 于 2017-10-26 18:55 编辑

·如果说你希望定制的容器是不可变的话,你只需要定义__len__()和__getitem__()方法。
·如果你希望定制的容器是可变的话,出了__len__()和__getitem__()方法,你还需要定义__setitem__()和__delitem__()两个方法
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-27 23:38:59 | 显示全部楼层

047魔法方法:定制序列(中2)

本帖最后由 摆渡终极鉴黄师 于 2017-10-28 01:58 编辑

上下文管理(with语句)

__enter__(self) 1.定义当使用with语句时的初始化行为
2.__enter__的返回值被with语句的目标或者as后的名字绑定

__exit__(self, exc_type,exc_value,traceback) 1.定义当一个代码被执行或者终之后上下文管理器应该做什么
2.一般被用来处理异常,清楚工作或者做一些代码块执行完毕之后的日常工作。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-29 11:59:01 | 显示全部楼层

047魔法方法:定制序列(中3)

本帖最后由 摆渡终极鉴黄师 于 2017-10-29 12:15 编辑

容器类型
__len__(self)                 定义当使用with语句时的初始化行为(返回容器中元素的个数)

__getitem__(self,key)定义获取容器中指定元素的行为,相当于self[key]

__setitem__(self, key, value)定义设置容器中指定元素的行为,相当于self[key] = value

__delitem__(self, key, value)定义删除容器中指定元素的行为,相当于 del self[key]

__iter__(self)                定义当迭代容器中的元素的行为

__reversed__(self)        定义当被reversed()调用时的行为

__contains__(self, item)定义当使用成员测试运算符(in 或 not in)时的行为
                               
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-30 16:04:25 | 显示全部楼层
本帖最后由 摆渡终极鉴黄师 于 2017-10-30 16:10 编辑

__len__(self)
返回容器的长度。可变和不可变容器都要实现它,这是协议的一部分

__getitem__(self, key)
定义当某一项被访问时,使用self[key]所产生的行为。这也是可变容器和不可变容器协议的一部分。如果键的类型错误将产生TypeError;如果key没有合适的值则产生KeyError

__setitem__(self, key, value)
定义当一个条目被赋值时,使用self[key] = value所产生的行为。这也是可变容器协议的一部分。而且,在相应的情形下也会产生KeyError和TypeError

__delitem__(self, key)
定义当某一项被删除时所产生的行为。(例如del self[key])。这是可变容器协议的一部分。当你使用一个无效的键时必须抛出适当的异常。

__iter__(self)
返回一个迭代器,尤其是当内置的iter()方法被调用的时候,以及当使用for x in container:方式进行循环的时候。
迭代器要求实现next方法(python3.x中改为__next__),并且每次调用这个next方法的时候都能获得下一个元素,元素用尽时触发 StopIteration 异常。
而其实 for 循环的本质就是先调用对象的__iter__方法,再不断重复调用__iter__方法返回的对象的 next 方法,触发 StopIteration 异常时停止,并内部处理了这个异常,所以我们看不到异常的抛出。
这种关系就好像接口一样,如果回顾以前几篇的魔法方法,可以发现许多的内置函数得到的结果就是相应的魔法方法的返回值。
可迭代对象:对象实现了一个__iter__方法,这个方法负责返回一个迭代器。
迭代器:内部实现了next(python3.x为__next__)方法,真正负责迭代的实现。当迭代器内的元素用尽之后,任何的进一步调用都之后触发
StopIteration 异常,所以迭代器需要一个__iter__方
法来返回自身。所以大多数的迭代器本身就是可迭代对象。这使两者的差距进一步减少。
但是两者还是不同的,如果一个函数要求一个可迭代对象(iterable),而你传的迭代器(iterator)并没有实现__iter__方法,那么可能会出现错误。
不过一般会在一个类里同时实现这两种方法(即是可迭代对象又是迭代器),此时__iter__方法只要返回self就足够的了。当然也可以返回其它迭代器。

__reversed__(self)
实现当reversed()被调用时的行为。应该返回序列反转后的版本。仅当序列是有序的时候实现它,例如列表或者元组

__contains__(self, item)
定义了调用in和not in来测试成员是否存在的时候所产生的行为。这个不是协议要求的内容,但是你可以根据自己的要求实现它。当__contains__没有被定义的时候,Python会迭代这个序列,并且当找到需要的值时会返回True
(从网上拷贝的一份感觉很有质量的笔记)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-10-31 19:58:02 | 显示全部楼层
本帖最后由 摆渡终极鉴黄师 于 2017-10-31 23:31 编辑

__missing__(self, key)

其在dict的子类中被使用。它定义了当一个不存在字典中的键被访问时所产生的行为。(例如,如果我有一个字典d,当"george"不是字典中的key时,使用了d["george"],此时d.__missing__("george")将会被调用)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-1 16:43:41 | 显示全部楼层

047魔法方法:定制序列(下)

本帖最后由 摆渡终极鉴黄师 于 2017-11-1 17:19 编辑

class CountList:        #把一个类定义成为一个容器
    def __init__(self, *args):        #Ta的这个参数*args参数是可变类型的,可变数量的,初始化一下
        self.values = [x for x in args]                #把用户传进去的这一堆数据把Ta放到这个列表里边,通过这个列表推导式的形式,把Ta存放进这个values推导式的里边
        self.count = {}.fromkeys(range(len(self.values)), 0)        #初始化用fromkeys就可以了,加一个内部方法,这里是使用Ta的下标而不是使用Ta的元素,然后全部初始化为0,刚开始是没有访问的

    def __len__(self):                #这是一个不可变的一个容器,所以要定义一个len和一个getitem
        return len(self.values)        #len的话是直接返回len(self.values)的值

    def __getitem__(self, key):                #这个key是Ta的相应的下标
        self.count[key] += 1        #这里要获取Ta的值,就会访问Ta一次。这里的self.count Ta对应的key就要+=1。获取Ta的值,就会访问Ta一次
        return self.values[key]               
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-2 13:08:26 | 显示全部楼层

048魔法方法:迭代器(上)

本帖最后由 摆渡终极鉴黄师 于 2017-11-2 13:33 编辑

迭代的意思呢就类似于循环——每一次重复的过程被称之为一次迭代的过程,而每一次迭代得到的结果将会被用来作为下一次迭代的初始值,提供迭代方法的容器我们称之为迭代器。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-3 06:27:39 | 显示全部楼层

048魔法方法:迭代器(中)

本帖最后由 摆渡终极鉴黄师 于 2017-11-3 06:53 编辑

>>> for i in "Kuang3":        #字符串就是一个容器,同时也是一个迭代器
        print(i)

       
K
u
a
n
g
3
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-4 14:56:04 | 显示全部楼层

048魔法方法:迭代器(下)

本帖最后由 摆渡终极鉴黄师 于 2017-11-4 15:55 编辑

内置函数iter()仅仅是调用了对象的__iter()方法,所以list对象内部一定存在方法iter__()
内置函数next()仅仅是调用了对象的__next()方法,所以list对象内部一定不存在方法next__(),但是Itrator中一定存在这个方法。
for循环内部事实上就是先调用iter()把Iterable变成Iterator在进行循环迭代的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-5 14:43:33 | 显示全部楼层

049乱入:生成器(上)

本帖最后由 摆渡终极鉴黄师 于 2017-11-5 14:46 编辑

所谓协同程序就是可以运行的独立函数调用,函数可以暂停或挂起,并在需要的时候从程序离开的地方继续或者重新开始。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-6 17:10:24 | 显示全部楼层

049乱入:生成器(中)

本帖最后由 摆渡终极鉴黄师 于 2017-11-6 17:23 编辑

>>> def myGen():
        print("生成器被执行!")
        yield 1        #        一但函数中出现yield语句,那么这个函数就被定义为了一个生成器,相当于return语句,但是普通函数return返回,那么这个函数就结束,但是对于生成器来说,出现yield,Ta就会把yield右边的这个参数给返回去,然后就会暂停在这里
        yield 2

       
>>> myG = myGen()
>>> next(myG)
生成器被执行!
1
>>> next(myG)
2                #        2就打印出来了,上边没有打印
>>>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-7 16:44:00 | 显示全部楼层

049乱入:生成器(中2)

本帖最后由 摆渡终极鉴黄师 于 2017-11-7 17:00 编辑

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

       
>>> myG = myGen()
>>> for i in myGen():
        print(i)

       
生成器被执行
1
2
>>> def libs():
        a = 0
        b = 1
        while True:
                a, b = b, a + b
                yield a

               
>>> for each in libs():                #        没有元素的时候会跳出StopIteration,python的for循环会自动调用next方法和探测StopIteration,结束
        if each > 100:
                break
        print(each, end=' ')

       
1 1 2 3 5 8 13 21 34 55 89
>>>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-8 17:13:39 | 显示全部楼层

049乱入:生成器(下)

本帖最后由 摆渡终极鉴黄师 于 2017-11-8 17:55 编辑

>>> e = (i for i in range(10))
>>> e
<generator object <genexpr> at 0x0000000002EC4FC0>                #        不是元祖(tuple)推导式,居然是生成器(generator)推导式,圆括号括起来的那个就是生成器推导式,生成器就是迭代器
>>> next(e)
0
>>> next(e)
1
>>> next(e)
2
>>> for each in e:
        print(each)

       
3
4
5
6
7
8
9
>>>

生成器推导式,如果作为函数的参数,可以直接写这个推导式就可以了,不用加圆括号,例如:
>>> sum(i for i in range(100) if i % 2)
2500
>>> sum((i for i in range(100) if i % 2))
2500
>>>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-9 08:02:16 | 显示全部楼层

050模块:模块就是程序(上)

本帖最后由 摆渡终极鉴黄师 于 2017-11-9 08:13 编辑

模块——>更高级的封装
·容器->数据的封装
·函数->语句的封装
·类->方法和属性的封装
·模块->模块就是程序
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-26 15:33

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表