您的位置:首页 > 编程语言 > Python开发

python知识-面向对象编程

2015-12-24 09:43 573 查看
class Person:

    def __init__(self,name):

        self.name=name

p1=Person('Xiao Ming')

p2=Person('Wang Wu')

在Python中,类通过 class 关键字定义。以
Person 为例,定义一个Person类如下:

class Person(object):

    pass

按照 Python 的编程习惯,类名以大写字母开头,紧接着是(object),表示该类是从哪个类继承下来的。

创建实例属性

例如,给xiaohong这个实例加上name、school和grade属性:

xiaohong = Person()

xiaohong.name = 'Xiao Hong'

xiaohong.school = 'No. 1 High School'

xiaohong.grade = 2

实例的属性可以像普通变量一样进行操作:

xiaohong.grade = xiaohong.grade + 1

初始化实例属性

在定义 Person 类时,可以为Person类添加一个特殊的__init__()方法,当创建实例时,__init__()方法被自动调用,我们就能在此为每个实例都统一加上以下属性:

class Person(object):

    def __init__(self, name, gender, birth):

        self.name = name

        self.gender = gender

        self.birth = birth

__init__() 方法的第一个参数必须是 self(也可以用别的名字,但建议使用习惯用法),后续参数则可以自由指定,和定义函数没有任何区别

相应地,创建实例时,就必须要提供除 self 以外的参数:

xiaoming = Person('Xiao Ming', 'Male', '1991-1-1')

xiaohong = Person('Xiao Hong', 'Female', '1992-2-2')

访问限制

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

class Person(object):

    def __init__(self, name):

        self.name = name

        self._title = 'Mr'

        self.__job = 'Student'

p = Person('Bob')

如果一个属性以"__xxx__"的形式定义,那它又可以被外部访问了,以"__xxx__"定义的属性在Python的类中被称为特殊属性,有很多预定义的特殊属性可以使用,通常我们不要把普通属性用"__xxx__"定义。

以单下划线开头的属性"_xxx"虽然也可以被外部访问,但是,按照习惯,他们不应该被外部访问。

创建类属性

class Person(object):

    address = 'Earth'

    def __init__(self, name):

        self.name = name

因为类属性是直接绑定在类上的,所以,访问类属性不需要创建实例,就可以直接访问:

print Person.address

对一个实例调用类的属性也是可以访问的,所有实例都可以访问到它所属的类的属性:

p1 = Person('Bob')

p2 = Person('Alice')

由于Python是动态语言,类属性也是可以动态添加和修改的:

Person.address = 'China'

print p1.address

类属性和实例属性名字冲突怎么办

修改类属性会导致所有实例访问到的类属性全部都受影响,但是,如果在实例变量上修改类属性会发生什么问题呢?

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'。

可见,当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。

当我们把 p1 的 address 实例属性删除后,访问 p1.address 就又返回类属性的值 'Earth'了:

del p1.address

print p1.address

定义实例方法

实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的:

class Person(object):

    def __init__(self, name):

        self.__name = name

    def get_name(self):

        return self.__name

p1 = Person('Bob')

print p1.get_name()  # self不需要显式传入

# => Bob

方法也是属性

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

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()

定义类方法

和属性类似,方法也分实例方法和类方法。

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

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

class Person(object):

    count = 0

    @classmethod

    def how_many(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()

通过标记一个 @classmethod,该方法将绑定到 Person
类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于
Person.count
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python