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

[Python 实战] - No.8 Python面向对象编程

2017-10-22 15:32 381 查看
面向对象三大关键:封装、继承、多态。我们从这三个方面介绍Python的面向对象编程,同时会提到Python中类的魔术方法:

1. 封装成类:

在Python中,我们使用以下方式进行类的声明:

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

def sayHello(self):
print 'Hi~ I am %s' % (self.name)

p = Person('xiaoming', 'male')
p.sayHello()


这里需要讲解的是以下几点:
1. __init__(self,...):类似于python的构造函数,不过同时python的成员变量也需要生命在__init__(self,...)中。类内部的所有成员函数均需要一个默认的self参数,并且需要放在第一位,作用类似于我们在java中的this一样

2. 在python中,公有,私有通过下划线来表示 。__xx或者__func(self):表示该变量或者函数是私有的,在外部无法获取。公有的属性(成员变量或者函数)使用xxx 或者__xxx__来表示。我们一般直接使用变量名来表示公有的成员变量,使用__xx__来表示特殊的公有属性

3. 由于python是一个动态的语言,所以我们可以给实例化的对象绑定新的变量。这仅对于我们自己声明的类对象,内置的类是不可以的



我们可以使用dir(p)来查看p对象的属性:



python使用@classmethod 和 直接在类中创建属性来获得类方法和类变量(类似于java中的static方法和变量)

class Person(object):

count = 0

@classmethod
def objNum(cls):
return cls.count
def __init__(self, name, gender):
self.name = name
self.gender = gender
Person.count = Person.count + 1

def sayHello(self):
print 'Hi~ I am %s' % (self.name)

print Person.count # 打印 0
p = Person('xiaoming', 'male') # 执行一次__init__(self)函数, count= 1
print p.count # 打印1
print Person.objNum() #打印1
在java中,我们会声明属性,设置get和set方法,在python中同样有类似的用法:
# _*_ coding = utf-8 _*_
class Person(object):

count = 0

@classmethod
def objNum(cls):
return cls.count

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

@property
def gender(self):
return self.__gender

@gender.setter
def gender(self, gender):
if gender == 'male' or gender == 'female':
self.__gender = gender
else:
raise ValueError("Wrong Gender")

def sayHello(self):
print 'Hi~ I am %s' % (self.name)

p = Person('xiaoming','male')
p.gender = 'xmale'运行程序,会抛出ValueError




二、继承:

在Person类下面,我们声明一个Boy类,来继承Person

# _*_ coding = utf-8 _*_
class Person(object):

count = 0

@classmethod
def objNum(cls):
return cls.count

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

def sayHello(self):
print 'Hi~ I am %s' % (self.name)

class Boy(Person):
def __init__(self,name,gender,hobby):
super(Boy, self).__init__(name, gender)
self.hobby = hobby

b = Boy('xiaoming','male','coding')
print b.name,b.gender,b.hobby
同时,python也可以很好的实现多根继承:
# _*_ coding = utf-8 _*_
class Person(object):

count = 0

@classmethod
def objNum(cls):
return cls.count

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

def sayHello(self):
print 'Hi~ I am %s' % (self.name)

class Player(object):

def __init__(self,game):
self.game = game

def playgame(self):
print 'Play game %s' % (self.game)

class Boy(Person,Player):
def __init__(self,name,gender,game,hobby):
Person.__init__(self,name, gender)
Player.__init__(self,game)
self.hobby = hobby

b = Boy('xiaoming','male','LOL','coding')
print b.name,b.gender,b.game,b.hobby
这里跟单根集成不同的地方是,我们在子类的__init__(self,...)函数中,采用了不同的方法调用父类__init__(),总结一下,有以下两种方法:
1. super(Derived,self).__init__(arg1,arg2)

2. Base.__init__(self,args1..)

第一种方法仅适用于单根,第二种单根多根均可以,推荐使用第二种

三、多态:

python的多态没有什么特殊性,也很简单。给上述Person 和Boy添加sayHello函数

# _*_ coding = utf-8 _*_
class Person(object):

count = 0

@classmethod
def objNum(cls):
return cls.count

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

def sayHello(self):
print 'Hi~ I am Person %s' % (self.name)

class Player(object):

def __init__(self,game):
self.game = game

def playgame(self):
print 'Play game %s' % (self.game)

class Boy(Person,Player):
def __init__(self,name,gender,game,hobby):
Person.__init__(self,name, gender)
Player.__init__(self,game)
self.hobby = hobby

def sayHello(self):
print 'Hi~ I am Boy %s' % (self.name)

def sayHello(x):
x.sayHello()

b = Boy('xiaoming','male','LOL','coding')
p = Person('xiaoming','male')
sayHello(b)
sayHello(p)

4. 魔术方法:
python的class中有很多魔术方法,这些魔术方法是我们不需要直接调用但是python的某些函数或者操作会调用的特殊方法。这类方法均为用双下划线包围的函数,例如__str__。在我们对一个对象使用print 函数的时候,就会调用到对象的__str__()函数。如果我们对类中的一些魔术方法进行覆写,就会得到我们想要的结果

例如,我们给Person添加一个__str__()方法:

# _*_ coding = utf-8 _*_
class Person(object):

count = 0

@classmethod
def objNum(cls):
return cls.count

def __init__(self, name, gender):
self.name = name
self.gender = gender
Person.count = Person.count + 1
def __str__(self):
return "I'm Person %s" % (self.name)

def sayHello(self):
print 'Hi~ I am Person %s' % (self.name)

p = Person('xiaoming','male')
print p就会打印我们的想要的 I'm Person xiaoming
在前面我们讲到了,可以给具体的实例对象绑定属性。如果我们不希望一个实例可以随意的添加属性呢?

我们可以使用__slots__,这会声明类允许的属性列表:

# _*_ coding = utf-8 _*_
class Person(object):

count = 0
__slots__ = ('name','gender')
@classmethod
def objNum(cls):
return cls.count

def __init__(self, name, gender):
self.name = name
self.gender = gender
Person.count = Person.count + 1
def __str__(self):
return "I'm Person %s" % (self.name)

def sayHello(self):
print 'Hi~ I am Person %s' % (self.name)

p = Person('xiaoming','male')
p.score = 123
print p就会报错,提示该对象没有属性score。
python中还有很多我们常用到的魔术方法,比如表示比较的__cmp__,表示长度的__len__,和将对象变为可调用对象,使得对象可以直接变成函数来返回结果的__call__等,这里不再赘述
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: