面向对象编程

Posted HHello_World

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象编程相关的知识,希望对你有一定的参考价值。

创建类:

class Person(object):
    pass

xiaoming = Person()
xiaohong = Person()

print xiaoming
print xiaohong
print xiaoming==xiaohong

 创建实例属性:Python是动态语言,对每一个实例,都可以直接给他们的属性赋值,实例的属性可以像普通变量一样进行操作。

#xiaoming和xiaohong是同一个类的对象
xiaoming = Person()
xiaoming.name = \'Xiao Ming\'
xiaoming.gender = \'Male\'
xiaoming.birth = \'1990-1-1\'


xiaohong = Person()
xiaohong.name = \'Xiao Hong\'
xiaohong.school = \'No. 1 High School\'
xiaohong.grade = 2


xiaohong.grade = xiaohong.grade + 1

初始化实例属性:__init__()方法,创建实例时,该方法自动调用

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

 

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

     以"__xxx__"定义的属性在Python的类中被称为特殊属性,有很多预定义的特殊属性可以使用,通常我们不要把普通属性用"__xxx__"定义。

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

 

类属性:实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个。

class Person(object):
    address = \'Earth\'
    def __init__(self, name):
        self.name = name

 

当实例属性和类属性重名时,实例属性优先级高。要在实例上修改类属性,它实际上并没有修改类属性,而是给实例绑定了一个实例属性。

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

 

定义实例方法:

  • 一个实例的私有属性就是以__开头的属性,无法被外部访问,可以在类的内部访问
  • 实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的
class Person(object):

    def __init__(self, name):
        self.__name = name

    def get_name(self):
        return self.__name
  •  class 中定义的实例方法其实也是属性,它实际上是一个函数对象,可以动态地添加到实例上,只是需要用 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()
    # => A
    p2 = Person(\'Alice\', 65)
    print p2.get_grade()
    # ERROR: AttributeError: \'Person\' object has no attribute \'get_grade\'
    # 因为p2实例并没有绑定get_grade
  • 函数调用不需要传入 self,但是方法调用需要传入 self。

定义类方法:通过标记一个 @classmethod,该方法将绑定到类上,而非类的实例。

  • 类方法无法获得任何实例变量,只能获得类的引用。
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()

 

继承:

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

class Teacher(Person):

    def __init__(self, name, gender, course):
        super(Teacher,self).__init__(name,gender)
        self.course=course

t = Teacher(\'Alice\', \'Female\', \'English\')
print t.name
print t.course

 

isinstance():判断变量的类型

  isinstance(t,Person)   判断t是不是Person类实例

多态:对于同一方法,根据调用者不同而产生不同结果

 

多重继承:继承多个父类

 

多重继承通过 super()调用__init__()方法时,A 虽然被继承了两次,但__init__()只调用一次

class D(B, C):
    def __init__(self, a):
        super(D, self).__init__(a)
        print \'init D...\'

 获取对象信息:

  • type()函数获取类型   
    >>> type(123)
    <type \'int\'>
  •  dir() 函数获取变量的所有属性
    >>> dir(123)   # 整数也有很多属性...
    [\'__abs__\', \'__add__\', \'__and__\', \'__class__\', \'__cmp__\', ...]
  •  getattr() 和 setattr():已知一个属性名称,要获取或者设置对象的属性
    getattr(s, \'name\')  # 获取name属性
    setattr(s, \'name\', \'Adam\')  # 设置新的name属性

 特殊方法:

__str__():print自动调用,用于显示给用户

__repr__():用于显示给开发人员

__cmp__():sorted()函数按照默认__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.score > s.score:
            return -1
        elif self.score == s.score:
            if self.name < s.name:
                return -1
            else:
                return 1
        else:
            return 1

L = [Student(\'Tim\', 99), Student(\'Bob\', 88), Student(\'Alice\', 99)]
print sorted(L)

__len__():返回元素个数,len()函数调用

class Fib(object):
    L=[0,1]

    def __init__(self, num):
        for i in range(2,num):
            j=Fib.L[i-1]+Fib.L[i-2]
            Fib.L.append(j)

    def __len__(self):
        return len(Fib.L)
    
    def __str__(self):
        return str(Fib.L)

f = Fib(10)
print f
print len(f)

 

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

 

__int__():int()函数自动调用

__float__():float()函数自动调用

 

 

@property:

  • 重新实现一个属性的setter和getter方法
class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.__score = score
    @property
    def score(self):
        return self.__score
    @score.setter
    def score(self, score):
        if score < 0 or score > 100:
            raise ValueError(\'invalid score\')
        self.__score = score
  • 将一个方法 转换为只读属性
class Student(object):

    def __init__(self, name, score):
        self.name = name
        self.__score = score

    @property
    def score(self):
        return self.__score

    @score.setter
    def score(self, score):
        if score < 0 or score > 100:
            raise ValueError(\'invalid score\')
        self.__score = score

    @property
    def grade(self):
        if self.score>=80:
            return \'A\'
        elif self.score<60:
            return \'C\'
        else:
            return \'B\'

s = Student(\'Bob\', 59)
print s.grade

s.score = 60
print s.grade

s.score = 99
print s.grade

 

__slots__:一个类允许的属性列表,限制当前类能拥有的属性

 

class Person(object):

    __slots__ = (\'name\', \'gender\')

    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

class Student(Person):

    __slots__ = (\'score\',)  #在Person类的基础上增加score属性

    def __init__(self,name,gender,score):
        super(Student,self).__init__(name,gender)
        self.score=score
        

s = Student(\'Bob\', \'male\', 59)
s.name = \'Tim\'
s.score = 99
print s.score

 

__call__:把一个实例变成可调用对象需要实现的方法

class Fib(object):
    def __call__(self, num):
        a, b, L = 0, 1, []
        for n in range(num):
            L.append(a)
            a, b = b, a + b
        return L

f = Fib()
print f(10)

 

以上是关于面向对象编程的主要内容,如果未能解决你的问题,请参考以下文章

面向面试编程代码片段之GC

Scala的面向对象与函数编程

面向对象编程

面向过程编程与面向对象编程

Java面向对象

面向对象编程(OOP)