面对对象编程

 多态:可对不同类型的对象执行相同的操作,而这些操作就像“被施了魔法”一样能够正常运行。即无需知道对象属于哪个类就
可调用其方法
 封装:对外部隐藏有关对象工作原理的细节。
 继承:可基于通用类创建出专用类。

一.属性,函数,方法
将属性关联到一个普通函数,这样就没有特殊参数 self了(绑定到对象上)
>>> class F:
… pass

>>> def fun():
… print(‘Success’)

>>> f=F()
>>> f.method=fun
>>> f.method()
Success

二.深入讨论继承
1.判断一个类是否是另一个类的子类:issubclass
>>> class F1(object):
… pass

>>> class F2(F1):
… pass

>>> issubclass(F2,F1)
True

2.查找该类的基类:__bases__
>>> class F1(object):
… pass

>>> class F2(F1):
… pass

>>> F2.__bases__
(<class ‘__main__.F1’>,)
>>>

3.确定对象是否是特定类的实例:isinstance
>>> class F1(object):
… pass

>>> f=F1()
>>> isinstance(f,F1)
True

4.如果你要获悉对象属于哪个类(直接实例),可使用属性__class__
>>> class F1(object):
… pass

>>> class F2(F1):
… pass

>>> t=F2()
>>> t.__class__
<class ‘__main__.F2’>

或者:type()
>>> type(t)
<class ‘__main__.F2’>
>>> type(f)
<class ‘__main__.F1’>
>>>

三.多重继承
超类有同名方法时,位于前面的类的方法将覆盖位于后面的类的方法(交换超类的参数位置可改变前后)

四.接口和内省
1.检查所需的方法是否存在
①hasattr
>>> class F(object):
… def fun(self):
… pass

>>> f=F()
>>> hasattr(f,’fun’)
True

2.检查方法或属性是否可以调用
①callable,getattr
>>> class F(object):
… def fun(self):
… pass

>>> callable(getattr(f,’fun’,None))
True
>>> callable(getattr(f,’a’,None)) #a属性不存在时返回None,None显然不可调用
False

②setattr设置对象的属性
>>> getattr(f,’age’,’N/A’)
‘N/A’
>>> setattr(f,’age’,18)
>>> getattr(f,’age’,’N/A’)
18

具体操作请参考下面:

Python的hasattr() getattr() setattr() 函数使用方法详解

五.抽象基类:用于指定子类必须提供哪些功能,却不实现这些功能
from abc import ABC, abstractmethod
class Talker(ABC):
@abstractmethod
def talk(self):
pass

1.不能实例化
>>> t=Talker()
Traceback (most recent call last):
File “”, line 1, in
TypeError: Can’t instantiate abstract class Talker with abstract methods talk

2.继承的基类只有重写抽象基类中的所有抽象方法,才可以实例化

3.类的注册(注册为其”子类”,却不是真正意义上的子类)
>>> from abc import ABC,abstractmethod
>>> class F(ABC):
… @abstractmethod
… def f1(self):
… pass

>>> class A():
… def f2(self):
… pass

>>> F.register(A)
<class ‘__main__.A’>
>>> a=A()
>>> isinstance(a,F)
True
>>> issubclass(A,F)
True
>>> a.f1()
Traceback (most recent call last):
File “”, line 1, in
AttributeError: ‘A’ object has no attribute ‘f1’

0

抽象-函数

1.函数文档
>>> def fun(x):
… ‘just for test’
… return x**2

>>> fun.__doc__
‘just for test’

2.参数修改
①如果参数为可变的数据结构,比如列表,传参进去会被修改
>>> def change(x):
… x[0]=0

>>> a=[1,2,3]
>>> change(a)
>>> a
[0, 2, 3]
如何避免?传入列表的副本即可
>>> def change(x):
… x[0]=0

>>> a=[1,2,3]
>>> change(a[:])
>>> a
[1, 2, 3]

②参数是不可变的
返回值并赋值

3.参数类型
①关键字参数;有助于澄清各个参数的作用,也可乱序,同时也可指定默认值
>>> def hello(name=’gonel’,greet=’Hello’):
… print(‘{},{}’.format(greet,name))

>>> hello(greet=’Hi’,name=’xiaoming’)
Hi,xiaoming
>>> hello(name=’xiaoming’)
Hello,xiaoming
>>> hello()
Hello,gonel

②收集参数
*args:收集参数并形成元组,但不收集关键字参数
>>> def fun(*args,x=100):
… print(args,x)

>>> fun(1,2,3,4,5,x=80)
(1, 2, 3, 4, 5) 80

**args:收集参数并形成字典,收集关键字参数
>>> def fun(**args):
… print(args)

>>> fun(x=1,y=2,z=3)
{‘x’: 1, ‘y’: 2, ‘z’: 3}
>>>

③分配参数
*args:使用运算符**,可将元组中的值分配给参数
>>> def add(x,y):
… print(x+y)

>>> a=(5,6)
>>> add(a)
Traceback (most recent call last):
File “”, line 1, in
TypeError: add() missing 1 required positional argument: ‘y’
>>> add(*a)
11

**args:使用运算符**,可将字典中的值分配给关键字参数
>>> def add(x=5,y=6):
… print(x+y)

>>> a={‘z’:4,’t’:6}
>>> add(**a)
Traceback (most recent call last):
File “”, line 1, in
TypeError: add() got an unexpected keyword argument ‘z’ #关键字参数声明得相同
>>> a={‘x’:4,’y’:6}
>>> add(**a)
10

总结:只有在定义函数(允许可变数量的参数)或调用函数时(拆分字典或序列)使用,星号才能发挥作用。

4.作用域
修改全局变量:global
修改外部作用域(嵌套函数):nonlocal
>>> def f1(a):
… def f2():
… nonlocal a
… a+=1
… return a
… return f2

>>> f=f1(5)
>>> f()
6

5.函数式编程
①map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回
>>> l=[1,2,3,4,5]
>>> list(map(f,l))
[1, 4, 9, 16, 25]

②reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4),最后返回最终结果
>>> from functools import reduce
>>> def add(x,y):
… return x+y

>>> l=[1,2,3,4,5]
>>> reduce(add,l)
15

③filter()也接收一个函数和一个序列,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素,返回一个Iterator
>>> def judge(x):
… return x.isalpha()

>>> l=[‘1′,’2′,’a’,’b’,’c’]
>>> list(filter(judge,l))
[‘a’, ‘b’, ‘c’]

0

条件语句,循环语句和其他语句

一.条件语句
1.if语句
status = “friend” if name.endswith(“Gumby”) else “stranger”
如果条件(紧跟在if后面)为真,表达式的结果为提供的第一个值(这里为”friend”),否则为第二个值(这里为”stranger”)。

2.断言(让程序在错误条件出现时立即崩溃胜过以后再崩溃)
>>> age=120
>>> assert 20“, line 1, in
AssertionError

>>> age=120
>>> assert 20“, line 1, in
AssertionError: The age is out of range

二.循环语句
注意:只要能使用for就不用while

1.字典的迭代

dict的迭代

2.一些迭代工具
①并行迭代
>>> names=[‘a’,’b’,’c’]
>>> ages=[20,21,23]
>>> for i in range(len(names)):
… print(names[i],’:’,ages[i])

a : 20
b : 21
c : 23

或者:内置函数zip,它将两个序列“缝合”起来,并返回一个由元组组成的序列
>>> names=[‘a’,’b’,’c’]
>>> ages=[20,21,23]
>>> for name,age in zip(names,ages):
… print(name,’:’,age)

a : 20
b : 21
c : 23
注意:当缝合的两个序列长度不同时,在最短的序列用完后停止缝合

②迭代时获取索引
使用内置函数enumerate
>>> names=[‘a’,’b’,’c’]
>>> for index,name in enumerate(names):
… print(index,’:’,name)

0 : a
1 : b
2 : c

③反向迭代和排序后再迭代
sorted()返回排序后的列表
reversed()返回逆置后的序列(可用list()查看)

3.列表推导
>>> [x for x in list(range(20)) if x%3==0]
[0, 3, 6, 9, 12, 15, 18]
生成器表达式:把上述方括号换成圆括号

三.三人行
1.pass:啥都不做

2.del:垃圾回收或者删除对象

3.exec:将字符串作为代码执行;无返回值
添加第二个参数-字典,用作代码字符串的命名空间,不会污染全局命名空间
>>> from math import sqrt
>>> scope={}
>>> exec(‘sqrt=1’,scope)
>>> sqrt(4)
2.0
>>> scope[‘sqrt’]
1

4.eval:计算用字符串表示的Python表达式的值,并返回结果
>>> eval(input(‘Input:’))
Input:20-3*4
8

0

print语句、import语句和赋值语句

一.print语句
1.用逗号分隔
>>> print(‘age:’,25)
age: 25

2.’+'(字符串和字符串)
>>> print(‘Hello’+’,’+’gonel’)
Hello,gonel

3.自定义分割符默认为空格)
>>> print(‘Hello’,’gonel’) #默认
Hello gonel

>>> print(‘Hello’,’gonel’,sep=’-‘) #Separate
Hello-gonel

4.自定义结束字符串
>>> print(‘Hello,’);print(‘gongel’)
Hello,
gongel
>>> print(‘Hello,’,end=”);print(‘gongel’) #如果将结束字符串指定为空字符串,以后就可继续打印到当前行。
Hello,gongel

二.import语句
import somemodule(使用时需要代入somemodule.somefunction())
from somemodule import somefunction(直接使用somefunction(),但是不可以使用该模块的其他函数)
from somemodule import *(直接使用somefunction(),同样使用该模块的其他函数)
定义别名:
from somemodule import somefunction as fun

三.赋值语句
1.序列解包
>>> x, y, z = 1, 2, 3
>>> print(x, y, z)
1 2 3

>>> x,y=1,2
>>> y,x=x,y#交换
>>> print(x,y)
2 1

>>> values=1,2,3
>>> values #元组
(1, 2, 3)
>>> x,y,z=values
>>> print(x,y,z)
1 2 3

可用*收集多余的值,带星号的变量最终包含的总是一个列表
>>> l=[1,2,3,4]
>>> x,y,*z=l
>>> print(x,y,z)
1 2 [3, 4]

>>> a,*b,c=’abc’
>>> print(a,b,c)
a [‘b’] c

2.链式赋值
>>> a=b=c=d=5
>>> print(a,b,c,d)
5 5 5 5

3.增强赋值
+= -= /= *=

0