python学习笔记07----面向对象(类与对象)

简介

虽然Python是解释性语言,但是它是面向对象的,能够进行对象编程。下面就来了解一下如何在Python中进行对象编程。

类是对现实世界中一些事物的封装。在人类认知中,会根据属性相近把东西归类,并且给类别命名。比如说,鸟类的共同属性是有羽毛,通过产卵生育后代。而且,这些鸟还有共同的行为,如飞行、名叫。任何一只特别的鸟都在鸟类的原型基础上的。接下来以鸟为例来介绍类的用法。

1
2
3
4
5
6
7
8
9
10
11
12

class Bird: #创建类--鸟
have_feather = True #定义类的属性(have_feather、way_of_reproduction、song均是该类的属性)
way_of_reproduction = "egg"
song="叽叽喳喳"
def sing(self): #定义类的方法(self必不可少)
print(self.song)
def move(self):
print("飞飞飞飞飞")
mybird=Bird() #实例化类的对象,可以使用这个对象访问类中的方法和属性
mybird.sing() #访问类中的方法(对象名.方法)
print("mybird通过"+mybird.way_of_reproduction+"繁殖") #访问类中的属性(+号的作用是连接字符串)

输出结果为:

1
2
3

叽叽喳喳
mybird通过egg繁殖

小小的总结一下,我们定义了一个类(class),就是鸟(Bird)。在该类中,我们定义了三个变量,一个是有羽毛(have_feather),一个是生殖方式(way_of_reproduction),还有一个是叫声(叽叽喳喳),这几个变量就是类的属性(attribute)。我们还定义个两个函数,一个是鸣叫(sing(self)),另一个是移动(move(self)),这两个函数就是类的方法(method)。

类建好了之后,我将类实例化为一个叫mybird的对象,并利用这个对象对类的属性和方法进行访问。

子类

鸟可以继续细分为鸡、鸭、鹅…..这就是所谓的子类。

1
2
3
4
5
6
7
8
9
10
11
12

class Chicken(Bird): #继承上例中的Bird
song="喔喔喔喔喔!" #重写父类中的属性
def move(self): #重写父类中的方法
print("这种移动方式已经废弃",end="--->") #end的作用是把字符串末尾的换行符替换为“--->”
super().move() #调用父类中的方法(对象是没有super()的)
print("跑跑跑跑跑")


myChicken=Chicken()
myChicken.move()
myChicken.sing()

多重继承

1
2
3
4
5
6
7
8
9
10
11
12
13

class Calculator:
def calculate(self,expression):
self.value=eval(expression) #计算字符串中的表达式
class Talker:
def talk(self):
print("结果为",self.value)
class TalkCalculator(Calculator,Talker): #本类不做任何事情,但是同时继承两个子类,这种行为叫做多重继承
pass #pass是空语句,是为了保持程序结构的完整性。

myCal=TalkCalculator()
myCal.calculate("4+2")
myCal.talk()

Tips

1.多态、封装与继承

多态:意味着可以对不同类的对象进行相同的操作。

封装:对外部世界隐藏类的细节。

继承:以普通的类为基础建立专门的类的对象。

2.面向对象概念

类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。

数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。

方法重载:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重载。

实例变量:定义在方法中的变量,只作用于当前实例的类。

继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟”是一个(is-a)”关系(例图,Dog是一个Animal)。

实例化:创建一个类的实例,类的具体对象。

方法:类中定义的函数。

对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

3.子类如何调用父类中的方法

1
2
3
4
5
6

class B(A):
def method(self, arg):
# A.method(self,arg) #1直接写类名调用
# super(B, self).method(arg) #2用 super(type, obj).method(arg)方法调用
super().method(arg) #3在类定义中调用本类的父类方法,可以直接super().method(arg)

4.方法中的self

类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,但是在调用这个方法的时候你不为这个参数赋值,Python会提供这个值。这个特别的变量指对象本身,按照惯例它的名称是self。

面向对象之续

特殊的方法

init方法

init方法在类的一个对象被建立时,马上运行。你可以利用这个方法对对象进行初始化。init方法类似于C++、C#和Java中的 constructor 。(注意:init的两边各有两条下划线)

1
2
3
4
5
6
7
8

class Person:
def __init__(self, name): #在__init__中初始化name
self.name = name
def sayHi(self):
print ("大家好,我是人贱人爱的", self.name)
p = Person("王尼玛")
p.sayHi()

del方法

del在对象消逝的时候被调用。对象消逝即对象不再被使用,它所占用的内存将返回给系统作它用。del方法与 destructor 的概念类似。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

class Person:
'''Represents a person.''' #通过Person.__doc__查看
population = 0

def __init__(self, name):
'''Initializes the person's data.'''
self.name = name
print ('(Initializing %s)' % self.name) #格式化输出字符串.

# When this person is created, he/she
# adds to the population
Person.population += 1 #类的变量在引用的时候是 类名.类变量

def __del__(self):
'''I am dying.'''
print ('%s says bye.' % self.name)

Person.population -= 1

if Person.population == 0:
print ('I am the last one.')
else:
print ('There are still %d people left.' % Person.population)

def sayHi(self): #可通过Person.sayHi.__doc__查看
'''Greeting by the person.

Really, that's all it does.'''
print ('Hi, my name is %s.' % self.name)

def howMany(self):
'''Prints the current population.'''
if Person.population == 1:
print ('I am the only person here.')
else:
print ('We have %d persons here.' % Person.population)

swaroop = Person('Swaroop')
swaroop.sayHi()
swaroop.howMany()

kalam = Person('Abdul Kalam')
kalam.sayHi()
kalam.howMany()
print(kalam.name) #对象变量

swaroop.sayHi()
swaroop.howMany()
print(swaroop.name)

输出:

1
2
3
4
5
6
7
8
9
10
11

(Initializing Swaroop)
Hi, my name is Swaroop.
I am the only person here.
(Initializing Abdul Kalam)
Hi, my name is Abdul Kalam.
We have 2 persons here.
Abdul Kalam
Hi, my name is Swaroop.
We have 2 persons here.
Swaroop

小提示

1.类成员的访问权限

Python中所有的类成员都是公共的,所有的方法都是有效的。
只有一个例外:如果你使用的数据成员名称以双下划线前缀比如__privatevar,Python的名称管理体系会有效地把它作为私有变量。
还有这样就有一个惯例,如果某个变量只想在类或对象中使用,就应该以单下划线前缀。而其他的名称都将作为公共的,可以被其他类/对象使用。记住这只是一个惯例,并不是Python所要求的(与双下划线前缀不同)。

2.类的变量与对象的变量

类的变量:由一个类的所有对象(实例)共享使用。当某个对象对类的变量做了改动的时候,这个改动会反映到所有其他的实例上。( 类名.类变量)
对象的变量:由类的每个对象/实例拥有。因此每个对象有自己对这个域的一份拷贝,即它们不是共享的,在同一个类的不同实例中,虽然对象的变量有相同的名称,但是是互不相关的。(对象名.变量)

3.print的格式化输出

支持参数格式化,与C语言的printf类似。

1
2
3

>>> strHello = "the length of (%s) is %d" %('Hello World',len('Hello World'))
>>> print (strHello)

输出

1
the length of (Hello World) is 11

1
2

>>> print("你好我的名字是%s,我今年%d岁了!" % ("王尼玛",2)) #注意,字符串与后面变量之间没有逗号!

输出

1
你好我的名字是王尼玛,我今年2岁了!