一.Python模块
导入模块:
>>> import math
>>> math.pow(2,2)
4.0
>>>
导入指定函数:
>>> from math import pow,sin,log
>>> pow(2,10)
1024.0
>>> sin(90)
0.8939966636005579
>>>
使用from example import function时出现的名字冲突问题:
>>> from math import log
>>> from logging import log as logger
>>> print log(10)
2.30258509299
>>> logger(10,'importt from logging')
>>>
动态导入模块:try:except ImportError:
>>> try:from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
使用__future__:
当新版本的一个特性与旧版本不兼容时,该特性将会在旧版本中添加到__future__中,以便旧的代码能在旧版本中测试新特性。
要试用某一新的特新,就可以导入__future__模块的功能来实现
在Python 2.7中:
>>> 10 / 3
3
在Python 3.x中:
>>> 10 / 3
3.3333333333333335
>>> 10 // 3
3
在2.7中试用3.x的功能:
>>> from __future__ import division
>>> print 10 / 3
3.3333333333333335
Python管理第三方模块的方式:
1.easy_install
2.pip(推荐,内置在2.7.9中)
确保安装了pip的情况下在命令提示符输入:pip install web.py(//第三方模块)等待下载就可以了
二.Python面向对象特征:
创建一个类,初始化两个该类的示例,进行打印和对比操作:
class Person(object):
pass
xiaoming=Person()
xiaohong=Person()
print xiaoming
print xiaohong
print xiaoming==xiaohong
>>>
<__main__.Person object at 0x02840970>
<__main__.Person object at 0x0295C650>
False
创建一个类,初始化三个类的实例,给增加属性(python是动态语言,对于每个属性都直接可以给他们赋值):
class Person(object):
pass
p1 = Person()
p1.name = 'Bart'
p2 = Person()
p2.name = 'Adam'
p3 = Person()
p3.name = 'Lisa'
L1 = [p1, p2, p3]
L2 = sorted(L1,lambda p1,p2:cmp(p1.name,p2.name))
print L2[0].name
print L2[1].name
print L2[2].name
>>>
Adam
Bart
Lisa
尽管python可以给示例随便增加属性,但是,现实世界中同一个类应该拥有相同的属性,此时我们使用__init__() 方法来同意定义属性,类似java中的构造方法,第一个参数必须是self,如下:
class Person(object):
def __init__(self, name, gender, birth):
self.name = name
self.gender = gender
self.birth = birth
创建实例的时候我们就可以这样了:
xiaoming = Person('Xiao Ming', 'Male', '1991-1-1')
xiaohong = Person('Xiao Hong', 'Female', '1992-2-2')
试编写除了接受固定参数之外还可以接受不确定的参数:**kw
class Person(object):
def __init__(self, name, gender, birth, **kw):
self.name = name
self.gender = gender
self.birth = birth
for k, v in kw.iteritems():
setattr(self, k, v)
xiaoming = Person('Xiao Ming', 'Male', '1990-1-1', job='Student')
print xiaoming.name
print xiaoming.job
访问限制:
属性前面加 '__' (双下划线) 就无法被外部访问。
xiaoming.__name='Xiao Ming'
前后都加 '__' 的为特殊属性,python中有很多预定义的特殊属性可以用,通常我们不需要把普通属性用 __xxx__ 定义。以
单下划线开头的属性"
_xxx"虽然也可以被外部访问,但是,按照习惯,他们不应该被外部访问。
class Person(object):
def __init__(self,name,score):
self.name=name
self.__score=score
p=Person('Bob',69)
print p.name
print p.__score
>>>
Traceback (most recent call last):
File "C:/Users/Administrator.2013-20140717HS/Desktop/aaa", line 7, in <module>
print p.__score
AttributeError: 'Person' object has no attribute '__score'
创建类属性:
class Person(object):
sex='M'
def __init__(self,name,score):
self.name=name
self.score=score
p1=Person('Bob',69)
p2=Person('Jim',89)
print p1.sex
print p1.sex
>>>
M
M
>>>
类属性也可以动态创建:
class Person(object):
sex='M'
def __init__(self,name,score):
self.name=name
self.score=score
Person.countrycode='CN'
p1=Person('Bob',69)
p2=Person('Jim',89)
print p1.sex
print p1.sex
print p1.countrycode
print p1.countrycode
>>>
M
M
CN
CN
>>>
类属性和示例属性冲突时:
class Person(object):
address = 'Earth'
def __init__(self, name):
self.name = name
p1 = Person('Bob')
p2 = Person('Alice')
print 'Person.address = ' + Person.address
p1.address = 'China'
print 'p1.address = ' + p1.address
print 'Person.address = ' + Person.address
print 'p2.address = ' + p2.address
>>>
Person.address = Earth
p1.address = China
Person.address = Earth
p2.address = Earth
可见,可见,当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。
原因是 p1.address = 'China'并没有改变 Person 的 address,而是给 p1这个实例绑定了实例属性address ,对p1来说,它有一个实例属性address(值是'China'),而它所属的类Person也有一个类属性address,所以:
访问 p1.address 时,优先查找实例属性,返回'China'。
访问 p2.address 时,p2没有实例属性address,但是有类属性address,因此返回'Earth'。
定义实例的方法:
实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数
class Person(object):
def __init__(self, name):
self.__name = name
def get_name(self):
return self.__name
定义类方法:
和属性类似,方法也分为实例方法和类方法,在class 中定义的全部是实例方法,实例方法的第一个参数是self本身。如下:@classmethod
class Person(object):
sex='M'
count=0
@classmethod
def many(cls):
return cls.count
def __init__(self,name):
self.name=name
Person.count=Person.count+1
print Person.many()
p=Person('Jim')
print Person.many()
>>>
0
1
>>>
通过标记一个
@classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count。
因为是在类上调用,而非实例上调用,因此类方法无法获得任何实例变量
,只能获得类的引用。
类的继承:
class Person(object):
def __init__(self,name,sex):
self.name=name
self.sex=sex
class Student(Person):
def __init__(self,name,sex,age):
super(Student,self).__init__(name,sex)
self.age=age
p=Person('Jim','M')
print p.name
s=Student('Tom','W',19)
print s.name
>>>
Jim
Tom
>>>
Python集成的特点:
总是从某一个类集成,默认继承object
调用super().__init__() 用来初始化父类
isinstance()判断类型
isinstance() 可以判断一个变量的类型,既可以用在python内置的数据类型又可以用在我们自己定义的类,本质上都是数据类型,拿上面的代码为例,判断:
print isinstance(p,Person)
print isinstance(p,Student)
print isinstance(s,Person)
print isinstance(s,Student)
>>>
True
False
True
True
>>>
多态
类具有继承关系,并且子类类型可以向上转型做父类类型,我们在给Person,Student,Teacher,都加上toString()方法
class Person(object):
def __init__(self,name,sex):
self.name=name
self.sex=sex
def toString(self):
return 'this is Person,person name is %s'%self.name
class Student(Person):
def __init__(self,name,sex,age):
super(Student,self).__init__(name,sex)
self.age=age
def toString(self):
return 'this is Studnet,student name is %s'%self.name
def f(x):
print x.toString()
p=Person('Jim','M')
s=Student('Alice','W',19)
f(p)
f(s)
>>>
this is Person,person name is Jim
this is Studnet,student name is Alice
>>>
说明:子类和父类分别有自己的toString()方法,方法调用作用在实例的实际类型上,Student实际上拥有自己的
toString()和来自父类的toString(),调用时总是先找到自己定义的toString(),如果找不到才会向上找,直到找到为止。
由于Python是动态语言,传递给f()的类型不一定是Person或者其子类,任何类型都可以。只要有一个toString()方法就可以,如下:
class Book(object):
def toString(self):
return 'book'
def f(x):
print x.toString()
b=Book()
f(b)
>>>
book
>>>
这是动态语言和静态语言(例如Java)最大的差别之一。动态语言调用实例方法,不检查类型,只要方法存在,参数正确,就可以调用。
多重继承:
class A(object):
def __init__(self, a):
self.a = a
class B(A):
def __init__(self, a):
super(B, self).__init__(a)
class C(A):
def __init__(self, a):
super(C, self).__init__(a)
class D(B, C):
def __init__(self, a):
super(D, self).__init__(a)
像这样,D 同时继承自 B 和 C,也就是 D 拥有了 A、B、C 的全部功能。多重继承通过 super()调用__init__()方法时,A 虽然被继承了两次,但__init__()只调用一次
多重继承的目的是从两种继承树中分别选择并继承出子类,以便组合功能使用。
例子:
+-Person
+- Student
+- Teacher
是一类继承树;
+- SkillMixin
+- BasketballMixin
+- FootballMixin
是一类继承树。
通过多重继承,请定义“会打篮球的学生”和“会踢足球的老师”。
class Person(object):
pass
class Student(Person):
pass
class Teacher(Person):
pass
class SkillMixin(object):
pass
class BasketballMixin(SkillMixin):
def skill(self):
return 'basketball'
class FootballMixin(SkillMixin):
def skill(self):
return 'football'
class BStudent(Student, BasketballMixin):
pass
class FTeacher(Teacher, FootballMixin):
pass
s = BStudent()
print s.skill()
t = FTeacher()
print t.skill()
获取对象信息:
type()
>>> type(123)
<type 'int'>
>>> s = Student('Bob', 'Male', 88)
>>> type(s)
<class '__main__.Student'>
dir()
>>> dir(123) # 整数也有很多属性...
['__abs__', '__add__', '__and__', '__class__', '__cmp__', ...]
>>> dir(s)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'gender', 'name', 'score', 'whoAmI']
dir()返回的属性是字符串列表,如果已知一个属性名称,要获取或者设置对象的属性,就需要用
getattr() 和
setattr( )函数了:
>>> getattr(s, 'name') # 获取name属性
'Bob'
>>> setattr(s, 'name', 'Adam') # 设置新的name属性
>>> s.name
'Adam'
>>> getattr(s, 'age') # 获取age属性,但是属性不存在,报错:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'age'
>>> getattr(s, 'age', 20) # 获取age属性,如果属性不存在,就返回默认值20:
20
特殊方法:
__str__:把一个类变成str
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)
Python 定义了
__str__()和
__repr__()两种方法,
__str__()用于显示给用户,而
__repr__()用于显示给开发人员。
__cmp__:
对 int、str 等内置数据类型排序时,Python的 sorted() 按照默认的比较函数 cmp 排序,但是,如果对一组 Student 类的实例排序时,就必须提供我们自己的特殊方法__cmp__():
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 __cmp__(self, s):
if self.name < s.name:
return -1
elif self.name > s.name:
return 1
else:
return 0
上述 Student 类实现了__cmp__()方法,
__cmp__用实例自身
self和传入的实例
s 进行比较,如果
self 应该排在前面,就返回 -1,如果
s 应该排在前面,就返回1,如果两者相当,返回 0。
__len__
如果一个类表现得像一个list,要获取有多少个元素,就得用 len() 函数。
要让 len() 函数工作正常,类必须提供一个特殊方法__len__(),它返回元素的个数。
class Students(object):
def __init__(self, *args):
self.names = args
def __len__(self):
return len(self.names)
斐波那契数列是由 0, 1, 1, 2, 3, 5, 8...构成。
请编写一个Fib类,Fib(10)表示数列的前10个元素,print Fib(10) 可以打印出数列的前 10 个元素,len(Fib(10))可以正确返回数列的个数10。
class Fib(object):
def __init__(self, num):
a, b, L = 0, 1, []
for n in range(num):
L.append(a)
a, b = b, a + b
self.numbers = L
def __str__(self):
return str(self.numbers)
__repr__ = __str__
def __len__(self):
return len(self.numbers)
f = Fib(10)
print f
print len(f)
数学运算:
定义一个Rational 和加减乘除预算
def gcd(a, b):
if b == 0:
return a
return gcd(b, a % b)
class Rational(object):
def __init__(self, p, q):
self.p = p
self.q = q
def __add__(self, r):
return Rational(self.p * r.q + self.q * r.p, self.q * r.q)
def __sub__(self, r):
return Rational(self.p * r.q - self.q * r.p, self.q * r.q)
def __mul__(self, r):
return Rational(self.p * r.p, self.q * r.q)
def __div__(self, r):
return Rational(self.p * r.q, self.q * r.p)
def __str__(self):
g = gcd(self.p, self.q)
return '%s/%s' % (self.p / g, self.q / g)
__repr__ = __str__
r1 = Rational(1, 2)
r2 = Rational(1, 4)
print r1 + r2
print r1 - r2
print r1 * r2
print r1 / r2
>>>
3/4
1/4
1/8
2/1
>>>
类型转换:
Rational类实现了有理数运算,但是,如果要把结果转为 int 或 float 怎么办?要让int()函数正常工作,只需要实现特殊方法__int__():
class Rational(object):
def __init__(self, p, q):
self.p = p
self.q = q
def __int__(self):
return self.p // self.q
__slots__
__slots__是指一个类允许的属性列表:__slots__的目的是限制当前类所能拥有的属性,如果不需要添加任意动态的属性,使用__slots__也能节省内存。
class Student(object):
__slots__ = ('name', 'gender', 'score')
def __init__(self, name, gender, score):
self.name = name
self.gender = gender
self.score = score
__call__
一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法 __call__()。我们把 Person 类变成一个可调用对象:
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