python中的一点小知识与库(5)

目录:
1. 不可变对象
2. 关于迭代器
3. 内建函数
4. 类特殊方法,属性
5. 装饰器

一、不可变对象

python中的不可变对象:str,integer,tuple(和JAVA还是挺像的,Java中的String,Integer,Long都是不可变的)

可变类型(immutable)类型:list, dict

二、关于迭代器

1.什么是迭代

可以直接作用于for循环的对象统称为可迭代对象(Iterable)。

可以被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator)。

所有的Iterable均可以通过内置函数iter()来转变为Iterator。

iterable需要包含有iter()方法用来返回iterator,而iterator需要包含有next()方法用来被循环

2.实现

参见yield说明:http://blog.csdn.net/youyou1543724847/article/details/72187536

这和JAVA很不想,Java里这有yield()函数,是线程对象的一个方法,表示放弃CPU,让给其他线程执行。另外,Java里的迭代是通过内部的迭代器实现了,记住了上次的pos,一次一次移动的。

三、内建函数

建函数功用在于其往往可对多种类型对象进行类似的操作,即多种类型对象的共有的操作;如果某种操作只对特殊的某一类对象可行,Python常将其设置为该种类型的方法(method)

1.内建函数的查看

通过 dir(__builtins__)查看。

ArithmeticError,AssertionError,AttributeError,BaseException,BlockingIOError,BrokenPipeError,BufferError,BytesWarning,ChildProcessError
,ConnectionError,ConnectionRefusedError,ConnectionResetError,DeprecationWarning,EOFError,Ellipsis,EnvironmentError,Exception,False
,FileNotFoundError,FloatingPointError,FutureWarning,GeneratorExit,IOError,ImportError,ImportWarning,IndentationError,IndexError
,IsADirectoryError,KeyError,KeyboardInterrupt,LookupError,MemoryError,ModuleNotFoundError,NameError,None,NotADirectoryError
,NotImplementedError,OSError,OverflowError,PendingDeprecationWarning,PermissionError,ProcessLookupError,RecursionError,ReferenceError,ResourceWarning
,RuntimeWarning,StopAsyncIteration,StopIteration,SyntaxError,SyntaxWarning,SystemError,SystemExit,TabError,TimeoutError
,TypeError,UnboundLocalError,UnicodeDecodeError,UnicodeEncodeError,UnicodeError,UnicodeTranslateError,UnicodeWarning,UserWarning,ValueError
,WindowsError,ZeroDivisionError,


__build_class__,__debug__,__doc__,__import__,__loader__,__name__,__package__
,abs,all,any,ascii,bin,bool,bytearray,bytes,callable
,classmethod,compile,complex,copyright,credits,delattr,dict,dir,divmod
,eval,exec,exit,filter,float,format,frozenset,getattr,globals
,hash,help,hex,id,input,int,isinstance,issubclass,iter
,license,list,locals,map,max,memoryview,min,next,object
,open,ord,pow,print,property,quit,range,repr,reversed
,set,setattr,slice,sorted,staticmethod,str,sum,super,tuple

2.常用内建函数说明

(1)dir() :查询对象的一些文档字符串(doc strings)列表,这些文档字符串主要包含对模块的介绍,方法功能的说明等

(2)数值类型相关的
bin() :获取一个整数的2进制形式的字符串,类似的函数还有oct(),hex()

(3)对象生成相关的
int() 将数值或字符串转换为整数int,完整使用形式int(x,base),base用于指定进制。类似的还有long(),float(),complex(),str(),list(),dic(),tuple()

(4)数值计算
sum() ,abs()

(5) id(obj):查看对象标识符,可认为id不同,对象不同(和==比较不同,==比较的是是值是否相同)

(5)集合相关的
all( iterable ):如果某个iterable对象里的所以元素都为真,则返回真
any(iterable ) : 只要有一个为真,则返回真

max(),min()

Java所有方法都是属于类,不知道Python里的这些内建方法是什么概念

四、类特殊方法

这种形如__xxx__的变量或者函数名就要注意,这些在Python中是有特殊用途的。

如:__len__()方法我们也知道是为了能让class作用于len()函数

1.strrepr方法:

类似与Java Object的toString()方法。

class Person(object):
    def __init__(self,name,gender):
        self.name = name
        self.gender =gender    
p = Person('Bob','male')
print (p)

输出:

<__main__.Person object at 0x01C44470>

实现了__str__(self)__函数后,效果:

class Person(object):
    def __init__(self,name,gender):
        self.name = name
        self.gender =gender
    def __str__(self):
        return '(Person:%s,%s)'%(self.name,self.gender)


p = Person('Bob','male')
print (p)

输出:(Person:Bob,male)

当我们输入p的时候我们并不能显示出字符串,因为 Python 定义了str()和repr()两种方法,str()用于显示给用户,而repr()用于显示给开发人员。

>>> class Person(object):
    def __init__(self,name,gender):
        self.name = name
        self.gender =gender
    def __str__(self):
        return '(Person:%s,%s)'%(self.name,self.gender)
    __repr__ = __str__


>>> p = Person('Bob','Male')
>>> p
(Person:Bob,Male)

2.__iter__方法

如果一个类想被用于for … in循环,类似list或tuple那样,就必须实现一个iter()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的__next__方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。

class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1 
    def __iter__(self):
        return self 
    def __next__(self):
        self.a, self.b = self.b, self.a + self.b
        if self.a > 10:
            raise StopIteration();
        return self.a 

for n in Fib():
    print(n)

从python 3开始,next变成了__next__形式

3.__getattr__ 和 __setter__方法

正常情况下,当我们调用类的方法或属性时,如果不存在,就会报错。

class Student(object):
    def __init__(self):
        self.name = 'Michael'

调用name属性,没问题,但是,调用不存在的score属性,就有问题了:

>>> print s.score
Traceback (most recent call last):
  ...
AttributeError: 'Student' object has no attribute 'score'

错误信息很清楚地告诉我们,没有找到score这个attribute。
要避免这个错误,除了可以加上一个score属性外,Python还有另一个机制,那就是写一个__getattr__()方法,动态返回一个属性。修改如下:

class Student(object):
    def __init__(self):
        self.name = 'Michael'
    def __getattr__(self, attr):
        if attr=='score':
            return 99

当调用不存在的属性时,比如score,Python解释器会试图调用__getattr__(self, 'score')来尝试获得属性。

注意,只有在没有找到属性的情况下,才调用getattr,已有的属性,比如name,不会在__getattr__中查找。
此外,注意到任意调用如s.abc都会返回None,这是因为我们定义的getattr默认返回就是None。要让class只响应特定的几个属性,我们就要按照约定,抛出AttributeError的错误:

class Student(object):
    def __getattr__(self, attr):
        if attr=='age':
            return lambda: 25
        raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)

类似的__setter__方法,就是当属性不存在时,调用的方法

4.比较类方法__eq__, __ne__, __lt__, __gt__

class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score
    def __str__(self):
        return '(%s: %s)' % (self.name, self.score)
    __repr__ = __str__


    def __lt__(self, s):
        if self.name < s.name:
            return True
        else:
            return False    

L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 77)]
print( sorted(L))

结果:

[(Alice: 77), (Bob: 88), (Tim: 99)]

这么多方法,好像在排序的时候,实现一个就可以了(不知道是不是在所有情况下都是这样,反正,sorted是可以的,如下面的例子,只实现gt也是一样的 )

class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score
    def __str__(self):
        return '(%s: %s)' % (self.name, self.score)
    __repr__ = __str__


    def __gt__(self, s):
        if self.name < s.name:
            return True
        else:
            return False    

L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 77)]
print( sorted(L))

5. __call__方法

实现call方法,这个类型就成为可调用的, 换句话说,我们可以把这个类的对象当作函数来使用,相当于重载了括号运算符。

5. __call__方法

实现call方法,这个类型就成为可调用的, 换句话说,我们可以把这个类的对象当作函数来使用,相当于重载了括号运算符。

6. 其他方法

(1)__len__()
(2) __contains__
(3) __delattr__
(4) __dir__
(5) __getattribute__
(6) __getitem__(key) : x[key]
(7) __setitem__(key, value) : x[key] = value
(8) __delitem__(key) : del x[key]
(9) __copy__() : copy.copy(x)
(10) __deepcopy__() : copy.deepcopy(x)
(12) __hash__() : hash(x)
(13) __new__() : x = MyClass()

8. 属性

(1)__self__:实例的该属性为实例本身

(2)Class().funcname.__func__ :返回方法所对应的底层函数(即所绑定的是那个函数)
(3)Class().funcname.__name__ :方法名字
(4)__name :类,方法名字
(5)__doc__ : 类,方法
(6)__module__ :类,实例,方法
(7)__bases__ : 类的基类
(8)__dict__ :类,实例的字典,存储相关属性信息
(9)Class.__mro__ : 类的属性查找解析顺序

class A:
    pass

class B(A):
    def func1(self):
        pass
    def func2(self,a):
        pass
class C(A):
    pass;
class D(B,C): 
    pass  
print(D().func1.__doc__)
print(D().func1.__name__)
print(D().func1.__module__)

输出:

None
func1
__main__

五、装饰器

参见:http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014318435599930270c0381a3b44db991cd6d858064ac0000

函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数。

比如有如下函数:

def now():
    print("now func")

现在,假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。

本质上,decorator就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的decorator,可以定义如下:

def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

观察上面的log,因为它是一个decorator,所以接受一个函数作为参数,并返回一个函数。我们要借助Python的@语法,把decorator置于函数的定义处:

@log
def now():
    print('2015-3-25')

调用now()函数,不仅会运行now()函数本身,还会在运行now()函数前打印一行日志:

>>> now()
call now():
2015-3-25

把@log放到now()函数的定义处,相当于执行了语句:

now = log(now)

如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,写出来会更复杂。比如,要自定义log的文本:

def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

这个3层嵌套的decorator用法如下:

@log('execute')
def now():
    print('2015-3-25')

和两层嵌套的decorator相比,3层嵌套的效果是这样的:

 now = log('execute')(now)

我们来剖析上面的语句,首先执行log(‘execute’),返回的是decorator函数,再调用返回的函数,参数是now函数,返回值最终是wrapper函数。

以上两种decorator的定义都没有问题,但还差最后一步。因为我们讲了函数也是对象,它有name等属性,但你去看经过decorator装饰之后的函数,它们的name已经从原来的’now’变成了’wrapper’:

因为返回的那个wrapper()函数名字就是’wrapper’,所以,需要把原始函数的name等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。

不需要编写wrapper.name = func.name这样的代码,Python内置的functools.wraps就是干这个事的,所以,一个完整的decorator的写法如下:

import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

或者针对带参数的decorator:

import functools

def log(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值