目录:
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.str和repr方法:
类似与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__
五、装饰器
函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数。
比如有如下函数:
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