Python进阶(三)

来源:互联网 发布:windows图形编程pdf 编辑:程序博客网 时间:2024/05/17 03:18

一.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 StringIOexcept ImportError:from StringIO import StringIO

使用__future__:

当新版本的一个特性与旧版本不兼容时,该特性将会在旧版本中添加到__future__中,以便旧的代码能在旧版本中测试新特性。

要试用某一新的特新,就可以导入__future__模块的功能来实现

在Python 2.7中:

>>> 10 / 33
在Python 3.x中:

>>> 10 / 33.3333333333333335>>> 10 // 33
在2.7中试用3.x的功能:
>>> from __future__ import division>>> print 10 / 33.3333333333333335


安装第三方模块:

Python管理第三方模块的方式:

1.easy_install

2.pip(推荐,内置在2.7.9中)

确保安装了pip的情况下在命令提示符输入:pip install web.py(//第三方模块)等待下载就可以了


二.Python面向对象特征:

创建一个类,初始化两个该类的示例,进行打印和对比操作:

class Person(object):    passxiaoming=Person()xiaohong=Person()print xiaomingprint xiaohongprint xiaoming==xiaohong>>><__main__.Person object at 0x02840970><__main__.Person object at 0x0295C650>False
创建一个类,初始化三个类的实例,给增加属性(python是动态语言,对于每个属性都直接可以给他们赋值):

class Person(object):    passp1 = 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].nameprint L2[1].nameprint L2[2].name>>>AdamBartLisa


初始化示例的属性:

尽管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.nameprint xiaoming.job

访问限制:

属性前面加 '__' (双下划线) 就无法被外部访问。

xiaoming.__name='Xiao Ming'
前后都加 '__' 的为特殊属性,python中有很多预定义的特殊属性可以用,通常我们不需要把普通属性用 __xxx__ 定义。以单下划线开头的属性"_xxx"虽然也可以被外部访问,但是,按照习惯,他们不应该被外部访问。

class Person(object):    def __init__(self,name,score):        self.name=name        self.__score=scorep=Person('Bob',69)print p.nameprint p.__score>>>Traceback (most recent call last):  File "C:/Users/Administrator.2013-20140717HS/Desktop/aaa", line 7, in <module>    print p.__scoreAttributeError: 'Person' object has no attribute '__score'

创建类属性:

class Person(object):    sex='M'    def __init__(self,name,score):        self.name=name        self.score=scorep1=Person('Bob',69)p2=Person('Jim',89)print p1.sexprint p1.sex>>> MM>>> 
类属性也可以动态创建:

class Person(object):    sex='M'    def __init__(self,name,score):        self.name=name        self.score=scorePerson.countrycode='CN'p1=Person('Bob',69)p2=Person('Jim',89)print p1.sexprint p1.sexprint p1.countrycodeprint p1.countrycode>>> MMCNCN>>> 

类属性和示例属性冲突时:

class Person(object):    address = 'Earth'    def __init__(self, name):        self.name = namep1 = Person('Bob')p2 = Person('Alice')print 'Person.address = ' + Person.addressp1.address = 'China'print 'p1.address = ' + p1.addressprint 'Person.address = ' + Person.addressprint 'p2.address = ' + p2.address>>>Person.address = Earthp1.address = ChinaPerson.address = Earthp2.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+1print Person.many()p=Person('Jim')print Person.many()>>> 01>>> 
通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count。因为是在类上调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用。

类的继承:

class Person(object):    def __init__(self,name,sex):        self.name=name        self.sex=sexclass Student(Person):    def __init__(self,name,sex,age):        super(Student,self).__init__(name,sex)        self.age=age        p=Person('Jim','M')print p.names=Student('Tom','W',19)print s.name>>> JimTom>>> 
Python集成的特点:

总是从某一个类集成,默认继承object

调用super().__init__() 用来初始化父类


isinstance()判断类型

isinstance() 可以判断一个变量的类型,既可以用在python内置的数据类型又可以用在我们自己定义的类,本质上都是数据类型,拿上面的代码为例,判断:

print isinstance(p,Person)print isinstance(p,Student)print isinstance(s,Person)print isinstance(s,Student)>>>TrueFalseTrueTrue>>> 

多态

类具有继承关系,并且子类类型可以向上转型做父类类型,我们在给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.nameclass 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.namedef f(x):    print x.toString()p=Person('Jim','M')s=Student('Alice','W',19)f(p)f(s)>>> this is Person,person name is Jimthis 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 = aclass 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)        

像这样,同时继承自 BC,也就是 D 拥有了 A、B、C 的全部功能。多重继承通过 super()调用__init__()方法时,A 虽然被继承了两次,但__init__()只调用一次

多重继承的目的是从两种继承树中分别选择并继承出子类,以便组合功能使用。

例子:

+-Person
  +- Student
  +- Teacher

是一类继承树;

+- SkillMixin
   +- BasketballMixin
   +- FootballMixin

是一类继承树。

通过多重继承,请定义“会打篮球的学生”和“会踢足球的老师”。

class Person(object):    passclass Student(Person):    passclass Teacher(Person):    passclass SkillMixin(object):    passclass BasketballMixin(SkillMixin):    def skill(self):        return 'basketball'class FootballMixin(SkillMixin):    def skill(self):        return 'football'class BStudent(Student, BasketballMixin):    passclass FTeacher(Teacher, FootballMixin):    passs = 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__:

对 intstr 等内置数据类型排序时,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和传入的实例 进行比较,如果 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 fprint 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 + r2print r1 - r2print r1 * r2print r1 / r2>>>3/41/41/82/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


0 0