1.迭代器:可以直接作用于for
循环的对象统称为可迭代对象:Iterable
,使用
isinstance()
判断一个对象是否是Iterable
对象:
>>> from collections import Iterable >>> isinstance([], Iterable) True >>> isinstance({}, Iterable) True >>> isinstance('abc', Iterable) True >>> isinstance((x for x in range(10)), Iterable) True >>> isinstance(100, Iterable) False
可以被next()
函数调用并不断返回下一个值的对象称为迭代器:Iterator,使用
isinstance()
判断一个对象是否是Iterator
对象:
>>> from collections import Iterator >>> isinstance((x for x in range(10)), Iterator) True >>> isinstance([], Iterator) False >>> isinstance({}, Iterator) False >>> isinstance('abc', Iterator) False
注意与Iterable 和 Iterator, list
、dict
、str
虽然是Iterable
,却不是Iterator,转化使用
iter()
函数:
>>> isinstance(iter([]), Iterator) True >>> isinstance(iter('abc'), Iterator) True
2.返回函数和闭包:
def lazy_sum(*args): def sum(): ax = 0 for n in args: ax = ax + n return ax return sum
当我们调用lazy_sum()
时,返回的并不是求和结果,而是求和函数:
>>> f = lazy_sum(1, 3, 5, 7, 9) >>> f <function lazy_sum.<locals>.sum at 0x101c6ed90>
内部函数sum
可以引用外部函数lazy_sum
的参数和局部变量,当lazy_sum
返回函数sum
时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”
3.匿名函数:与Java概念相似
lambda x: x * x
关键字lambda
表示匿名函数,冒号前面的x
表示函数参数。
4.装饰器:在代码运行期间为已定义好的函数动态增加功能的方式,称之为“装饰器”(Decorator):
>>> def now(): ... print('2015-3-25')
为其增加打印日志的功能:
def log(func): def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper @log def now(): print('2015-3-25')
借助Python的@语法,把log置于函数的定义处,把@log
放到now()
函数的定义处,相当于执行了语句:now = log(now)
log()
是一个decorator,返回一个函数,原来的now()
函数仍存在,只是现在同名的now
变量指向了新的函数,于是调用now()
将执行新函数,即在log()
函数中返回的wrapper()
函数。
wrapper()
函数的参数定义是(*args, **kw)
,因此,wrapper()
函数可以接受任意参数的调用。在wrapper()
函数内,首先打印日志,再紧接着调用原始函数。
5.偏函数:Python的functools
模块提供functools.partial()方法创建一个偏函数:
def int2(x, base=2): return int(x, base) >>> int2('1000000') 64 >>> int2('1010101') 85
使用functools.partial()方法自己定义int2:
>>> import functools >>> int2 = functools.partial(int, base=2) >>> int2('1000000') 64 >>> int2('1010101') 85
6.模块:与Java中的包相同,一个abc.py
的文件就是一个名字叫abc
的模块
内建的sys
模块为例,编写一个hello
的模块:
#!/usr/bin/env python3 --让这个hello.py文件直接在Unix/Linux/Mac上运行 # -*- coding: utf-8 -*- --表示.py文件本身使用标准UTF-8编码 ' a test module ' #--表示模块的文档注释,任何模块代码的第一个字符串都被视为模块的文档注释; __author__ = 'Michael Liao' #--作者名 import sys #--导入该模块,就可以访问sys模块的所有功能 def test(): args = sys.argv if len(args)==1: print('Hello, world!') elif len(args)==2: print('Hello, %s!' % args[1]) else: print('Too many arguments!') if __name__=='__main__': test()
最后两行:当我们在命令行运行hello
模块文件时,Python解释器把一个特殊变量__name__
置为__main__
,而如果在其他地方导入该hello
模块时,if
判断将失败,因此,这种if
测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试。
安装第三方模块:通过包管理工具pip完成的:
第三方库都会在Python官方的pypi.python.org网站注册,安装命令:
pip install Pillow
Anaconda,这是一个基于Python的数据处理和科学计算平台,它已经内置了许多非常有用的第三方库,可以尝试直接import numpy
等已安装的第三方模块
7.作用域:
__xxx__:
这样的变量是特殊变量,可以被直接引用,但是有特殊用途
abc:是公开的(public),可以被直接引用
_xxx
和__xxx
:是非公开的(private),不应该被直接引用(Python没有一种方法可以完全限制访问private函数或变量,从编程习惯上不应该引用private函数或变量)
8.类:
class Student(object): pass
(object)
表示该类是从哪个类继承下来的
class Student(object): def __init__(self, name, score): self.name = name self.score = score
创建实例的时候__init__()
方法可以强制绑定属性,__init__()
方法的第一个参数永远是self(指向创建的实例本身)但是创建实例的时候
self
不需要传
方法:第一个参数要是self
由于Python是动态语言,根据类创建的实例可以任意绑定属性。
9.访问限制:让内部属性不被外部访问,可以把属性的名称前加上两个下划线__
变成了一个私有变量(private),与Java相似可在class中设置get和set方法
10.继承和多态
:
继承:
class Animal(object): def run(self): print('Animal is running...') class Dog(Animal): pass class Cat(Animal): pass
多态:子类方法覆盖父类方法
静态语言 vs 动态语言:
静态语言(例如Java)来说,如果需要传入Animal
类型,则传入的对象必须是Animal
类型或者它的子类,否则,将无法调用run()
方法
Python这样的动态语言来说,则不一定需要传入Animal
类型。我们只需要保证传入的对象有一个run()
方法就可以了:
class Timer(object): def run(self): print('Start...')
这就是动态语言的“鸭子类型”:看起来像鸭子就把它当做鸭子吧!
11.获取对象信息:
判断对象类型:type()
函数
判断class的类型:isinstance()
函数,两个参数比较是否相同
获得一个对象的所有属性和方法:dir()
函数
类似__xxx__
的属性和方法在Python中都是有特殊用途的:__len__
方法返回长度:
>>> len('ABC') 3 >>> 'ABC'.__len__() 3
12.实例属性和类属性:
给实例绑定属性的方法:通过self
变量
class Student(object): def __init__(self, name): self.name = name s = Student('Bob') s.score = 90
给类(class)绑定属性的方法:与Java一样增加类属性
class Student(object): name = 'Student'
13.使用__slots__ :
动态语言可以给实例绑定任何属性和方法:
>>> def set_age(self, age): # 定义一个函数作为实例方法 ... self.age = age ... >>> from types import MethodType >>> s.set_age = MethodType(set_age, s) # 给实例绑定一个方法 >>> s.set_age(25) # 调用实例方法 >>> s.age # 测试结果 25
但是,给一个实例绑定的方法,对另一个实例是不起作用的,__slots__限制实例的属性,在定义class的时候,定义一个特殊的__slots__
变量来限制该class实例能添加的属性:
class Student(object): __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
>>> s = Student() # 创建新的实例 >>> s.name = 'Michael' # 绑定属性'name' >>> s.age = 25 # 绑定属性'age' >>> s.score = 99 # 绑定属性'score' Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Student' object has no attribute 'score'
注意:__slots__
定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
14.@property:既能检查参数,又可以用类似属性这样简单的方式来访问类的变量,@property
装饰器就是负责把方法变成属性调用的:
class Student(object): @property def get_score(self): return self._score @score.setter def set_score(self, value): if not isinstance(value, int): raise ValueError('score must be an integer!') if value < 0 or value > 100: raise ValueError('score must between 0 ~ 100!') self._score = value
把一个getter方法变成属性,只需要加上@property
就可以了,@property
本身又创建了另一个装饰器@score.setter
把一个setter方法变成属性赋值
还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性:
class Student(object): @property def birth(self): return self._birth @birth.setter --birth是可读写属性 def birth(self, value): self._birth = value @property --age就是一个只读属性 def age(self): return 2015 - self._birth
15.多重继承:与Java不同Python允许多继承
16.定制类:类似__slots__
这种形如__xxx__
有特殊用途的函数,可以帮助我们定制类
__str__:打印好看
__iter__:用于for ... in
循环
__getitem__:像list那样按照下标取出元素
__getattr__:动态返回一个属性
__call__:任何类,只需要定义一个__call__()
方法,就可以直接对实例进行调用
17.枚举类:枚举是列出某些有穷序列集的所有成员,Enum
类来实现这个功能:
from enum import Enum Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
这样我们就获得了Month
类型的枚举类
更精确地控制枚举类型可以从Enum
派生出自定义类:
from enum import Enum, unique @unique --@unique装饰器可以帮助我们检查保证没有重复值。 class Weekday(Enum): Sun = 0 # Sun的value被设定为0 Mon = 1 Tue = 2 Wed = 3 Thu = 4 Fri = 5 Sat = 6
来源:https://www.cnblogs.com/xussi/p/9044925.html