Python 类
python类
简介
面向对象是我们经常能听到的术语,即class,类。事实上,主角是两个,一个是类,一个是类实例。人类,是一个类,我们每一个人是一个人类的实例。而类之间又有一些关系,例如,我们既是人类,也是动物,更细化来讲,我们是哺乳类动物,灵长类,类似于集合的概念,哺乳动物属于动物,而在面向对象中我们通常称哺乳动物是动物的子类。而对于动物这个类来说,会自带一些属性,例如:年龄、体重。也会有一些方法:生殖、呼吸。而不同种类的动物(即动物类的各种子类)可能会有不同的属性或方法,像胎生、卵生,像鸟类的飞行的方法和豹子奔跑的方法。
定义
用关键字class去定义一个类,如果没有指定父类,默认继承object类。
class Human(object):
pass
这样,我们定义个了一个Human,人类。
类属性
class Human(object):
taisheng = True
为什么要叫类属性呢,因为这个属性是和类绑定的,并不是和实例绑定的。胎生这个属性是全人类共有的,并不是某个人特殊拥有的属性。
实例属性
class Human(object):
def __init__(self, name):
self.name = name
human_a = Human("alan")
我们首先实例化了一个人类human_a,然后给这个人类设置了一个实例属性name,name这个属性独立于其他的人类,是和实例绑定的,所以叫实例属性。
- 实例属性可以在实例创建后任意时间设置。
- 一般放在构造函数里__init()__
类方法
class Human(object):
def __init__(self, name):
self.name = name
def walk(self):
print self.name + " is walking"
human_a = Human("alan")
human_a.walk()
运行结果:
alan is walking
类的方法可以看做是一种类属性,而传入的第一个参数self,表示调用这个类方法的实例。像上面的例子,human_a调用了walk这个类方法,human_a的名字是alan,所以运行的结果就是alan is walking。
访问控制
从上面的例子来看,我们可以在外部随意更改name这个属性,如果不想让外部直接访问到,则在属性名字前加两个下划线__name,这样从外部就无法直接访问了。如果还是想访问,可以再加个get的接口。
class Human(object):
def __init__(self, name):
self.__name = name
def walk(self):
print self.name + " is walking"
def get_name(self):
return self.__name
human_a = Human("alan")
print human_a.get_name()
print human_a.__name
如果还是想更改__name字段,可以再加上一个set接口
class Human(object):
def __init__(self, name):
self.__name = name
def walk(self):
print self.name + " is walking"
def get_name(self):
return self.__name
def set_name(self, name):
self.__name = name
human_a = Human("alan")
print human_a.set_name("bob")
可能有人会有疑问,为何要这么“画蛇添足”呢?其不然,这样会增强代码的健壮性,直接暴漏属性可能会带来意想不到的后果,通过接口的方式可以加以控制,例如,我们可以通过set接口去限定name的长度。
class Human(object):
def __init__(self, name):
self.__name = name
def walk(self):
print self.name + " is walking"
def get_name(self):
return self.__name
def set_name(self, name):
if len(name) <= 10:
self.__name = name
human_a = Human("alan")
print human_a.set_name("bob")
这样就不会出现name过长的情况。
继承
最开始的简介里说到,哺乳动物是动物的一种,用面向对象的属于来说,哺乳动物是动物的子类,子类拥有父类的属性、方法,即继承。同时又可以拥有父类没有的属性和方法,即多态。 还是以人类为例,通常来说,人类又可以分为男人和女人(当然也有别的,23333)
class Man(Human):
def __init__(self, name, has_wife):
self.__name = name
self.__has_wife = has_wife
来,我们看下这个男人,多了一个新的属性,__has_wife(是否已婚)。我们写到了Man的构造函数里。其实通常并不这么写构造函数,假如Human里有很多属性、很多初始化步骤,我们Man继承的时候难不成要复制粘贴一遍Human的构造函数?当然不是啦,通常会这么写。
class Man(Human):
def __init__(self, name, has_wife):
super(Man, self).__init__(name)
self.__has_wife = has_wife
super(Man, self).__init__(name)等价于调用了父类Human的构造函数,就不用再复制粘贴一遍了。 既然有男人,那就再来个女人吧。
class Woman(Human):
def __init__(self, name, has_husband):
super(Woman, self).__init__(name)
self.__has_husband = has_husband
我们都道,男人和女人是不一样的,通常男人都自带抽烟、喝酒、烫头,啊。。。并没有烫头。
class Man(Human):
def __init__(self, name, has_husband):
super(Man, self).__init__(name)
self.__has_husband = has_husband
def smoke(self):
print "A man maybe smoke"
def drink(self):
print "A man maybe drink"
当然,女人也自带逛街、化妆等天赋技能。
class Woman(Human):
def __init__(self, name, has_husband):
super(Woman, self).__init__(name)
self.__has_husband = has_husband
def shopping(self):
print "A woman always go shopping"
def make_up(self):
print "A woman always make up"
好了,观众朋友们,有没有感觉到这种继承的优越性。可以很清晰地看到,男人和女人都有一些相同的属性,也有一些各自不同的方法。如果哪天人类有了别的方法、属性,直接在Human类更改,男人和女人也会自动继承。如果想再设计一个双性人这个类,那直接从Human继承就可以了,对男人和女人不会有任何影响。这就是面向对象的优越性啊!