python如何面向对象编程_python之面向对象编程浅谈

1.python中的类与对象

1 Python中定义类的方式比较简单:2

3 class类名:4

5 类变量6

7 def __init__(self,paramers):8

9 def函数(self,...)10

11 …...12

13 其中直接定义在类体中的变量叫类变量,而在类的方法中定义的变量叫实例变量。类的属性包括成员变量和方法,其中方法的定义和普通函数的定义非常类似,但方法必须以self作为第一个参数。

举例:

1 >>>classMyFirstTestClass:2

3 class Spec="it is a test class"

4

5 def__init__(self,word):6

7 print"say"+word8

9 defhello(self,name):10

11 print"hello"+name12

13

View Code

在Python类中定义的方法通常有三种:实例方法,类方法以及静态方法。这三者之间的区别是实例方法一般都以self作为第一个参数,必须和具体的对象实例进行绑定才能访问,而类方法以cls作为第一个参数,cls表示类本身,定义时使用@classmethod;而静态方法不需要默认的任何参数,跟一般的普通函数类似.定义的时候使用@staticmethod。

1 >>>classMethodTest():2

3 count=04

5 defaddCount(self):6

7 MethodTest.count+=1

8

9 print"I am an instance method,my count is"+str(MethodTest.count),self10

11 @staticmethod12

13 defstaticMethodAdd():14

15 MethodTest.count+=1

16

17 print"I am a static methond,my count is"+str(MethodTest.count)18

19 @classmethod20

21 defclassMethodAdd(cls):22

23 MethodTest.count+=1

24

25 print"I am a class method,my count is"+str(MethodTest.count),cls26

27

28

29 >>>

30

31 >>>a=MethodTest()32

33 >>>a.addCount()34

35 Iam an instance method,my count is 1 <__main__.methodtest instanceat>

36

37 >>>MethodTest.addCount()38

39

40

41 Traceback(most recent call last):42

43 File"", line 1, in

44

45 MethodTest.addCount()46

47 TypeError:unbound method addCount() must be called with MethodTest instance asfirst argument (got nothing instead)48

49 >>>a.staticMethodAdd()50

51 Iam a static methond,my count is252

53 >>>MethodTest.staticMethodAdd()54

55 Iam a static methond,my count is356

57 >>>a.classMethodAdd()58

59 Iam a class method,my count is4 __main__.MethodTest60

61 >>>MethodTest.classMethodAdd()62

63 Iam a class method,my count is5 __main__.MethodTest

View Code

从上面的例子来看,静态方法和类方法基本上区别不大,特别是有Java编程基础的人会简单的认为静态方法和类方法就是一回事,可是在Python中事实是这样的吗?看下面的例子:

1 >>>MethodTest.classMethodAdd()2

3 Iam a class method,my count is5 __main__.MethodTest4

5 >>>classsubMethodTest(MethodTest):6

7 pass

8

9 >>>b=subMethodTest()10

11 >>>b.staticMethodAdd()12

13 Iam a static methond,my count is614

15 >>>b.classMethodAdd()16

17 Iam a class method,my count is7 __main__.subMethodTest18

19 >>>a.classMethodAdd()20

21 Iam a class method,my count is8 __main__.MethodTest22

23 >>>

View Code

如果父类中定义有静态方法a(),在子类中没有覆盖该方法的话,Sub.a()仍然指的是父类的a()方法。而如果a()是类方法的情况下,Sub.a()指向的是子类。@staticmethod只适用于不想定义全局函数的情况。

2.python的封装

面向对象程序设计中的术语对象(Object)基本上可以看做数据(特性)以及由一系列可以存取、操作这些数据的方法所组成的集合。传统意义上的“程序=数据结构+算法”被封装”掩盖“并简化为“程序=对象+消息”。对象是类的实例,类的抽象则需要经过封装。封装可以让调用者不用关心对象是如何构建的而直接进行使用。

一个简单的Python类封装如下:

1 _metaclass_=type #确定使用新式类

2 classAnimal:3

4 def __init__(self): #构造方法 一个对象创建后会立即调用此方法

5 self.Name="Doraemon"

6 printself.Name7

8 def accessibleMethod(self): #绑定方法 对外公开

9 print "I have a self! current name is:"

10 printself.Name11 print "the secret message is:"

12 self.__inaccessible()13

14 def __inaccessible(self): #私有方法 对外不公开 以双下划线开头

15 print "U cannot see me..."

16

17 @staticmethod18 defstaticMethod():19 #self.accessibleMethod() #在静态方法中无法直接调用实例方法 直接抛出异常

20 print "this is a static method"

21

22 def setName(self,name): #访问器函数

23 self.Name=name24

25 def getName(self): #访问器函数

26 returnself.Name27

28 name=property(getName,setName) #属性 可读可写

View Code

构造函数和析构函数

Python的构造函数有两种,__init__和__new__,__init__的调用不会返回任何值,在继承关系中,为了保证父类实例正确的初始化,最好显示的调用父类的__init__方法。与__init__不同,__new__实际是个类方法,以cls作为第一个参数。

如果类中同时定义了__init__和__new__方法,则在创建对象的时候会优先使用__new__.

class A(object):

def __init__(self):

print("in init")

def __new__(self):

print("in new")

A()

如果__new__需要返回对象,则会默认调用__init__方法。利用new创建一个类的对象的最常用的方法为:super(currentclass,cls).__new__(cls[, ...])

class A(object):

def __new__(cls):

Object = super(A,cls).__new__(cls)

print "in New"

return Object

def __init__(self):

print "in init"

class B(A):

def __init__(self):

print "in B's init"

B()

__new__构造函数会可变类的定制的时候非常有用,后面的小节中会体现。

Python由于具有垃圾回收机制,通常不需要用户显示的去调用析构函数,即使调用,实例也不会立即释放,而是到该实例对象所有的引用都被清除掉后才会执行。

>>>class P:

def__del__(self):

print"deleted"

>>>class S(P):

def__init__(self):

print'initialized'

def__del__(self):

P.__del__(self)

print"child deleted"

>>>a=S()

initialized

>>>b=a

>>>c=a

>>>id(a),id(b),id(c)

(18765704,18765704, 18765704)

>>>del a

>>>del b

>>>del c

deleted

childdeleted

>>>

3. Python中的继承

Python同时支持单继承与多继承,继承的基本语法为class新类名(父类1,父类2,..),当只有一个父类时为单继承,当存在多个父类时为多继承。子类会继承父类的所有的属性和方法,子类也可以覆盖父类同名的变量和方法。在传统类中,如果子类和父类中同名的方法或者属性,在查找的时候基本遵循自左到右,深度优先的原则。如下列:

1 >>>classA:2

3 defsayhi(self):4

5 print'I am A hi'

6

7 >>>classB:8

9 defsayhi(self):10

11 print'I am B Hi'

12

13

14

15 >>>classC(A,B):16

17 pass

18

19 >>>d=C()20

21 >>>d.sayhi()22

23 Iam A hi24

25 >>>B.sayhi(d)26

27 Iam B Hi

View Code

单继承

1 _metaclass_=type #确定使用新式类

2 classAnimal:3

4 def __init__(self):5 self.Name="Animal"

6

7 defmove(self,meters):8 print "%s moved %sm." %(self.Name,meters)9

10 class Cat(Animal): #Cat是Animal的子类

11

12 def __init__(self): #重写超类的构造方法

13 self.Name="Garfield"

14

15 ## def move(self,meters): #重写超类的绑定方法

16 ## print "Garfield never moves more than 1m."

17

18 classRobotCat(Animal):19

20 def __init__(self): #重写超类的构造方法

21 self.Name="Doraemon"

22

23 ## def move(self,meters): #重写超类的绑定方法

24 ## print "Doraemon is flying."

25

26 obj=Animal()27 obj.move(10) #输出:Animal moved 10m.

28

29 cat=Cat()30 cat.move(1) #输出:Garfield moved 1m.

31

32 robot=RobotCat()33 robot.move(1000) #输出:Doraemon moved 1000m.

View Code

多重继承

1 classAnimal:2

3 defeat(self,food):4 print "eat %s" %food5

6 classRobot:7

8 deffly(self,kilometers):9 print "flyed %skm." %kilometers10

11 class RobotCat(Animal,Robot): #继承自多个超类

12

13 def __init__(self):14 self.Name="Doraemon"

15

16 robot=RobotCat() #一只可以吃东西的会飞行的叫哆啦A梦的机器猫

17 printrobot.Name18

19 robot.eat("cookies") #从动物继承而来的eat

20

21 robot.fly(10000000) #从机器继承而来的fly

View Code

需要注意的地方,即如果一个方法从多个超类继承,那么务必要小心继承的超类(或者基类)的顺序:

1 classAnimal:2

3 defeat(self,food):4 print "eat %s" %food5

6 def move(self,kilometers): #动物的move方法

7 pass

8

9 classRobot:10

11 def move(self,kilometers): #机器的move方法

12 print "flyed %skm." %kilometers13

14 class RobotCat(Animal,Robot): #继承自多个超类 如方法名称相同,注意继承的顺序

15 #class RobotCat(Robot,Animal):

16 def __init__(self):17 self.Name="Doraemon"

18

19 robot=RobotCat() #一只可以吃东西的会飞行的叫哆啦A梦的机器猫

20 printrobot.Name21

22 robot.eat("cookies") #从动物继承而来的eat

23

24 robot.move(10000000) #本来是要从机器继承move方法,但是因为继承的顺序,这个方法直接继承自动物而pass掉

View Code

关于继承的构造函数:

1.如果子类没有定义自己的构造函数,父类的构造函数会被默认调用,但是此时如果要实例化子类的对象,则只能传入父类的构造函数对应的参数,否则会出错

classAddrBookEntry(object):

'addressbook entry class'

def__init__(self, nm, ph):

self.name= nm

self.phone= ph

print'Created instance for:', self.name

defupdatePhone(self, newph):

self.phone = newph

print'Updated phone# for:', self.name

classEmplAddrBookEntry(AddrBookEntry):

'EmployeeAddress Book Entry class'

defupdateEmail(self, newem):

self.email= newem

print'Updated e-mail address for:', self.name

john= EmplAddrBookEntry('John Doe', '408-555-1212')

printjohn.name

2.如果子类定义了自己的构造函数,而没有显示调用父类的构造函数,则父类的属性不会被初始化

classAddrBookEntry(object):

'addressbook entry class'

def__init__(self, nm, ph):

self.name= nm

self.phone= ph

print'Created instance for:', self.name

defupdatePhone(self, newph):

self.phone = newph

print'Updated phone# for:', self.name

classEmplAddrBookEntry(AddrBookEntry):

'EmployeeAddress Book Entry class'

def__init__(self, nm, ph, id, em):

#AddrBookEntry.__init__(self, nm,ph)

self.empid= id

self.email= em

defupdateEmail(self, newem):

self.email= newem

print'Updated e-mail address for:', self.name

john= EmplAddrBookEntry('John Doe', '408-555-1212',42, 'john@spam.doe')

printjohn.email

printjohn.empid

输出:

john@spam.doe

42

Traceback(most recent call last):

printjohn.name

AttributeError:'EmplAddrBookEntry' object has no attribute 'name'

3.如果子类定义了自己的构造函数,显示调用父类,子类和父类的属性都会被初始化

classAddrBookEntry(object):

'addressbook entry class'

def__init__(self, nm, ph):

self.name= nm

self.phone= ph

print'Created instance for:', self.name

defupdatePhone(self, newph):

self.phone = newph

print'Updated phone# for:', self.name

classEmplAddrBookEntry(AddrBookEntry):

'EmployeeAddress Book Entry class'

def__init__(self, nm, ph, id, em):

AddrBookEntry.__init__(self, nm,ph)

self.empid= id

self.email= em

defupdateEmail(self, newem):

self.email= newem

print'Updated e-mail address for:', self.name

john= EmplAddrBookEntry('John Doe', '408-555-1212',42, 'john@spam.doe')

printjohn.email

printjohn.empid

printjohn.name

4.python的多态

1 classcalculator:2 defcount(self, args):3 return 1

4

5

6 calc = calculator() #自定义类型

7

8 from random importchoice9

10 obj = choice(['hello,world', [1, 2, 3], calc]) #obj是随机返回的 类型不确定

11 print(type(obj))12 print(obj.count('a'))#方法多态

View Code

对于一个临时对象obj,它通过Python的随机函数取出来,不知道具体类型(是字符串、元组还是自定义类型),都可以调用count方法进行计算,至于count由谁(哪种类型)去做怎么去实现我们并不关心。

1 #!/usr/bin/env python

2 #-*- coding:utf-8 -*-

3 classDuck:4 defquack(self):5 print("Quaaaaaack!")6

7 deffeathers(self):8 print("The duck has white and gray feathers.")9

10

11 classPerson:12 defquack(self):13 print("The person imitates a duck.")14

15 deffeathers(self):16 print("The person takes a feather from the ground and shows it.")17

18

19 defin_the_forest(duck):20 duck.quack()21 duck.feathers()22

23

24 defgame():25 donald =Duck()26 john =Person()27 in_the_forest(donald)28 in_the_forest(john)29

30

31 game()

View Code

就in_the_forest函数而言,参数对象是一个鸭子类型和person类型,它实现了两个类型的相同名称的方法,打印的内容不一样,只是因为

下面是运算符号(方法)的多态

1 defadd(x,y):2 return x+y3

4 print add(1,2) #输出3

5

6 print add("hello,","world") #输出hello,world

7

8 print add(1,"abc") #抛出异常 TypeError: unsupported operand type(s) for +: 'int' and 'str'

View Code

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值