Python学习笔记:三

##安装第三方模块

python 2.7.9版本内置pip,官方推荐。在命令行中使用

  • pip install xxx.py 安装第三方模块
  • 命令行输入python,进入python的命令行模式
  • import xxx

使用future

Python的新版本会引入新的功能,但是,实际上这些功能在上一个老版本中就已经存在了。要“试用”某一新的特性,就可以通过导入future模块的某些功能来实现。

future前后的下划线是两个_ -> __

在Python 3.x中,字符串统一为unicode,不需要加前缀 u,而以字节存储的str则必须加前缀 b。利用future的unicode_literals在Python 2.7中编写unicode字符串。

1
2
3
4
from __future__ import unicode_literals

s = 'am I an unicode?'
print isinstance(s, unicode)

面向对象

创建对象
class Person(object) : 这里的object可改为其他父类

实例化对象
p1 = Person() : 不需要new

实例化属性
p1.name = “小明” : 对象的属性可以直接添加,不用类似java那种每个对象类都创建了属性之后才可以使用。因为python是动态语言。

如果要使用类似Java构造方法的那种,看下一点

初始化实例属性
如果Person类应该在创建的时候就拥有 name、gender 和 birth 属性,那么我们在定义 Person 类时,可以为Person类添加一个init()方法,当创建实例时,init()方法被自动调用,我们就能在此为每个实例都统一加上以下属性:

1
2
3
4
5
class Person(object):
def __init__(self, name, gender, birth):
self.name = name
self.gender = gender
self.birth = birth

注意:这里的self参数是必须添加的,但是对外暴露的参数只有后面三个,也就是调用时只需要填写后面的三个参数

1
p1 = Person('name', 'man', '2012')

而一旦使用了__init__方法,调用时就必须要具备参数了

访问限制

Python对属性权限的控制是通过属性名来实现的,如果一个属性由双下划线开头(__),该属性就无法被外部访问。

单下划线  -> 表示保护 -> 从外部不能导入,from xx import xxx
双下划线 -> 表示私有 -> 子类无法继承
前后双下划线 -> 在Python中表示特殊功能的函数,一般自己定义不要使用这种方式。入__init__(self, options)方法
例如__init__方法,如果去掉前面的双下划线,p1.init就可以用了

将函数变为方法

在Python中方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 types.MethodType() 把一个函数变为一个方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import types
def fn_get_grade(self):
if self.score >= 80:
return 'A'
if self.score >= 60:
return 'B'
return 'C'

class Person(object):
def __init__(self, name, score):
self.name = name
self.score = score

p1 = Person('Bob', 90)
p1.get_grade = types.MethodType(fn_get_grade, p1, Person)
print p1.get_grade()
# => A
p2 = Person('Alice', 65)
print p2.get_grade()
# ERROR: AttributeError: 'Person' object has no attribute 'get_grade'
# 因为p2实例并没有绑定get_grade

定义类方法

在class中定义的全部是实例方法,实例方法第一个参数 self 是实例本身。

要在class中定义类方法,需要这么写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Person(object):
count = 0

@classmethod
def how_many(cls):
#类方法的第一个参数将传入类本身,通常将参数名命名为 cls
return cls.count

def __init__(self, name):
self.name = name
Person.count = Person.count + 1

print Person.how_many()
p1 = Person('Bob')
print Person.how_many()

上面的 cls.count 实际上相当于 Person.count

继承与拥有

Python中每个类必须继承,如果没有合适的父类,就用object
has 表明拥有。student和book是一个拥有的关系

在继承完成之后,__init__()方法中记得使用SonClass.__init__(父类初始化函数的参数)初始化父类的相关属性及方法,SonClass表明子类的类名称

1
2
3
4
5
6
7
8
9
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender

class Student(Person):
def __init__(self, name, gender, score):
SonClass.__init__(name, gender)
self.score = score

判断类型 isinstance

用于判断某一个类是否为另一个父类(完成继承之后,这个类可以叫做本类也可以叫做父类)。例如Student继承自Person,继承完成之后Student可以称为Person类型,也可以称为Student。用isinstance(s, Person)的返回值为true

多态

基本和java一样,根据不同的子类对象显示不同的结果

额外的:
由于Python是动态语言,所以任何类型的实例都可以,只要它有一个同名的方法即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#Python提供了open()函数来打开一个磁盘文件,并返回 File 对象。File
#对象有一个read()方法可以读取文件内容:
#例如,从文件读取内容并解析为JSON结果:
import json
f = open('/path/to/file.json', 'r')
print json.load(f)

#由于Python的动态特性,json.load()并不一定要从一个File对象读取内
#容。任何对象,只要有read()方法,就称为File-like Object,都可以传给#json.load()。

import json

class Students(object):
def read(self):
return r'["Tim", "Bob", "Alice"]'

s = Students()
print json.load(s)

#[u'Tim', u'Bob', u'Alice']

多重继承

详情请看下一篇博文: Python学习笔记(四) 多重继承及内部算法解析

定制类和特殊方法

__str__()
如果要把一个类的实例变成 str,就需要实现,类似于Java中的toString()方法,可以重写,然后在其中返回自己想要的结果。
print list 其实是 print list.__str__()

__repr__()
Python 定义了__str__()和__repr__()两种方法,__str__()用于显示给用户,而__repr__()用于显示给开发人员。

1
2
3
4
5
6
7
8
#有一个偷懒的定义__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__

__cmp__()
对 int、str 等内置数据类型排序时,Python的 sorted() 按照默认的比较函数 cmp 排序,但是,如果对一组 Student 类的实例排序时,就必须提供我们自己的特殊方法 cmp\()

__len__()
如果一个类表现得像一个list,要获取有多少个元素,就得用 len() 函数。

要让 len() 函数工作正常,类必须提供一个特殊方法len(),它返回元素的个数。

__slots__()
如果要限制添加的属性,例如,Student类只允许添加 name、gender和score 这3个属性,就可以利用Python的一个特殊的slots来实现。
顾名思义,__slots__是指一个类允许的属性列表,类似与枚举。添加的属性只能是slots中列出的的值,多了就会报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Student(object):
__slots__ = ('name', 'gender', 'score')
def __init__(self, name, gender, score):
self.name = name
self.gender = gender
self.score = score

>>> s = Student('Bob', 'male', 59)
>>> s.name = 'Tim' # OK
>>> s.score = 99 # OK
>>> s.grade = 'A' # Error
Traceback (most recent call last):
...
AttributeError: 'Student' object has no attribute 'grade'

__call__()
在Python中,函数其实是一个对象:

1
2
3
4
5
>>> f = abs
>>> f.__name__
'abs'
>>> f(-123)
123

由于 f 可以被调用,所以,f 被称为可调用对象。

所有的函数都是可调用对象。

一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__call__()。

把 Person 类变成一个可调用对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender

def __call__(self, friend):
print 'My name is %s...' % self.name
print 'My friend is %s...' % friend

>>> p = Person('Bob', 'male')
>>> p('Tim')
My name is Bob...
My friend is Tim...

单看 p(‘Tim’) 你无法确定 p 是一个函数还是一个类实例,所以,在Python中,函数也是对象,对象和函数的区别并不显著。