1.10 Python面向对象程序设计

本节目录如下:
1.10.1 类的定义与使用
1.10.2 私有成员与公有成员
1.10.3 数据成员
1.10.4 方法
1.10.5 属性
1.10.6 继承与重载
1.10.7 多态
1.10.8 特殊方法与运算符重载

1.10.1 类的定义与使用

Python 使用 class 关键字来定义类,class 关键字之后是一个空格,接下来是类的名字,如果派生自其他基类的话则需要把所有基类放到一对圆括号中并使用逗号分隔,然后是一个冒 号,最后换行并定义类的内部实现。 类名的首字母一般要大写,当然也可以按照自己的习惯定义类名,但是一般推荐参考惯例来命名,并在整个系统的设计和实现中保持风格一致,这一点对于团队合作非常重要。例如:
class Car(object):        #定义一个类,派生自 object类
	def infor(self):      #定义成员方法
		print(" This is a car ")

定义了类之后,就可以用来实例化对象,并通过“对象名.成员”的方式来访问其中的数据成员或成员方法,例如:

>>>car=Car()			 #实例化对象
>>>car.infor()			 #调用对象的方法
This is a car

在Python中,可以使用内置方法isinstance()来测试一个对象是否为某个类的实例,
例如:

>>>isinstance(car, Car)
True
>>>isinstance(car,str)
False

最后,Python提供了一个关键字 pass,执行的时候什么也不会发生,可以用在类和函
数的定义中或者选择结构中,表示空语句。 如果暂时没有确定如何实现某个功能,或者为
以后的软件升级预留空间,可以使用关键字 pass来“占位”。 例如,下面的代码都是合
法的:

>>>class A:
pass
>>>def demo():
pass
>>>if 5>3:
Pass

1.10.2 私有成员与公有成员

从形式上看,在定义类的成员时,如果成员名以两个下划线(__)开头则表示是私有成 员,但是Python并没有对私有成员提供严格的访问保护机制。 私有成员在类的外部不能 直接访问,一般是在类的内部进行访问和操作,或者在类外部通过调用对象的公有成员方 法来访问。另外,Python提供了一种特殊方式“对象名._类名__xxx”可以访问私有成员, 但这会破坏类的封装性,不推荐这样做(不过真的很难阻止别人这么做)。 公有属性是可 以公开使用的,既可以在类的内部进行访问,也可以在外部程序中使用。
>>>class A:
    def __init__(self,value1=0,value2=0):			#构造函数
		self._value1 = value1
		self.__value2 = value2					#私有成员
	def setValue(self, value1,value2): 			#成员方法
		self._value1 = value1
		self.__value2 = value2					#在类内部可以直接访问私有成员
	def show(self):								#成员方法
		print(self._value1)
		print(self.__value2)
>>>a=A()
>>>a._value1									#在类外部可以直接访问非私有成员
0
>>>a._A__value2									#在外部访问对象的私有数据成员
0

在Python中,以下画线开头和结束的成员名有特殊的含义,类定义中用下画线作为
变量名和方法名前缀和后缀来表示类的特殊成员。
(1)_xxx:保护成员,不能用from module import* 导入,只有类对象和子类对象可
以访问这些成员。
(2)__xxx__:系统定义的特殊成员
(3)__xxx:类中的私有成员,一般只有类对象自己能访问,子类对象也不能访问到
这个成员,但在对象外部可以通过“对象名.__类名__xxx”这样的特殊方式来访问。

注意:Python 中不存在严格意义上的私有成员。

1.10.3 数据成员

  数据成员用来说明对象特有的一些属性,如人的身份证号、姓名、年龄、性别、身高、学历,汽车的品牌、颜色、最高时速,蛋糕的名称、尺寸、配料,书的名字、作者、ISBN、出版社、出版日期,等等。   数据成员 可以大致分为两类: 属于对象的数据成员和属于类的数据成员。 属于对象的数据成员主要指在构造函数\_\_init\_\_()中定义的(当然也可以在其他成员方法中定义),定义和使用时必须以 self 作为前缀(这一点是必需的),同一个类的不同对象(实例)之间的数据成员之间互不影响;属于类的数据成员是该类所有对象共享的,不属于任何一个对象,在定义类时这类数据成员不在任何一个成员方法的定义中。 在主程序中或类的外部,对象数据成员属于实例(对象),只能通过对象名访问;而类数据成员属于类,可以通过类名或对象名访问。 另外,在Python中可以动态地为类和对象增加成员,这也是 Python动态类型的一种重要体现。
class Car(object):
	price=100000		#属于类的数据成员
def __init__(self,c):
	self.color=c		#属于对象的数据成员
car1=Car("Red")			#实例化对象
car2=Car("Blue")
print(car1.color, Car.price)		#访问对象和类的数据成员
Car.price=110000			#修改类的属性
Car,name='QQ'			#动态增加类的属性
car1.color="Yellow"		#修改实例的属性
print(car2.color, Car.price, Car.name)
print(car2.color, Car.price, Car.name)
def setSpeed(self, s):
	self.speed=s

动态为对象增加成员

import types
car1.setSpeed=types.MethodType(setSpeed,car1)	#动态为对象增加成员方法
car1.setSpeed(50)							#调用对象的成员方法
print(car1,speed)

利用类数据成员的共享性,可以实时获得该类的对象数量,并且可以控制该类可以创建的对象最大数量。 例如:

>>>class Demo(object):
	total=0
	def_new__(cls,*args,**kwargs):	#该方法在__init__()之前被调用
		if cls.total >=3:					#最多允许创建3个对象
			raise Exception('最多只能创建3个对象')
		else:
			return object.__new__(cls)
	def__init__(self):
		Demo.total=Demo.total+1

1.10.4 方法

  方法用来描述对象所具有的行为,例如,列表对象的追加元素、插人元素、删除元素排序,字符串对象的分隔、连接、排版、替换,烤箱的温度设置、烘烤,等等。   在类中定义的方法可以粗略分为四大类: **公有方法、私有方法、静态方法和类方法**.公有方法、私有方法一般是指属于对象的实例方法,其中私有方法的名字以两个下画线(_)开始。每个对象都有自己的公有方法和私有方法,在这两类方法中都可以访问属子类和对象的成员;公有方法通过对象名直接调用,私有方法不能通过对象名直接调用,只能在实例方法中通过 self调用或在外部通过Python 支持的特殊方式来调用。   类的所有实例方法都必须至少有一个名为 self的参数,并且必须是方法的第一个形参(加果有多个形参的话),self参数代表对象自身。 在类的实例方法中访问实例属性时需要以self为前级,但在外部通过对象名调用对象方法时并不需要传递这个参数,如果在外部通过类名调用属于对象的公有方法,需要显式为该方法的 self参数传递一个对象名,用来明确指定访问哪个对象的数据成员。   静态方法和类方法都可以通过类名和对象名调用,但不能直接访问属于对象的成员,只能访问属于类的成员。一般将cls作为类方法的第一个参数,表示该类自身,在调用类方法时不需要为该参数传递值。 例如下面的代码所演示:
>>>class Root:
	__total=0
	def__init__(self,v):			#构造函数
		self.__value=v
		Root.__total +=1
	def show(self):				#普通实例方法
		print('self.__value:',self.__value)
		print('Root.__total:',Root.__total)
		
	@classmethod				#修饰器,声明类方法
	def classShowTotal(cls):		#类方法
   	print(cls.__total)
	
	@staticmethod				#修饰器,声明静态方法
	def staticshowTotal():		#静态方法
		print(Root.__total)
>>>r=Root(3)
>>>r.classshowTotal()			#通过对象来调用类方法
1
>>>r,staticShowTotal()			#通过对象来调用静态方法
1
>>>r.show()
self._value:3
Root.__total:1
>>>rr=Root(5)
>>>Root.classShowTotal()			#通过类名调用类方法
2
>>>Root.staticShowTotal()		#通过类名调用静态方法
2

1.10.5 继承与重载

  公开的数据成员可以在外部随意访问和修改,很难控制用户修改时新数据的合法性。解决这一问题的常用方法是定义私有数据成员,然后设计公开的成员方法来提供对私有数据成员的读取和修改操作,修改私有数据成员时可以对值进行合法性检查,提高了程序的健壮性,保 证 了数据的完整性。 属性结合了公开数据成员和成员方法的优点,既可以像成员方法那样对值进行必要的检查,又可以像数据成员一样灵活地访问。   Python 2,x 中属性的实现有很多不如人意的地方. 在 Python 3.x 中 , 属性得到了较为完整的实现,支持更加全面的保护机制。 如果设置属性为只读,则无法修改其值,也无法为对象增加与属性同名的新成员,同时,也无法删除对象属性。 例如:
>>>class Test:
	def__init__(self,value):
		self.value=value			#私有数据成员

	@property					#修饰器,定义属性,提供对私有数据成员的访问
	def value(self):				#只读属性,无法修改和删除
		return self._value

1.10.6 继承与重载

  俗话说得好,“虎父无犬子”、“龙生龙,凤生凤,老鼠的儿子会打洞”,这在一定程度上说明了继承的重要性。 在面向对象编程中,继承是代码复用和设计复用的重要途径,是面向对象程序设计的重要特性之一,继承也是实现多态的必要条件之一。   设计一个新类时,如果可以继承一个已有的设计良好的类然后进行二次开发,无疑会大幅度减少开发 工作量,并且可以很大程度地保证质量。 在继承关系中,已有的、设计好的类称为父类或基类,新设计的类称为子类或派生类 派生类可以继承父类的公有成员,但是不能继承其私有成员。 如果需要在派生类中调用基类的方法,可以使用内置函数super() 或者通过“基类名. 方法名()”的方式来实现这一目的。 ### 单继承与多继承 顾名思义,单继承就是继承一个类,多继承就是继承多个类。
#类定义
class people:
    #定义基本属性
    name = ''
    age = 0
    #定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0
    #定义构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁。" %(self.name,self.age))

#单继承示例
class student(people):
    grade = ''
    def __init__(self,n,a,w,g):
        #调用父类的构函
        people.__init__(self,n,a,w)
        self.grade = g
    #覆写父类的方法
    def speak(self):
        print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))

#另一个类,多重继承之前的准备
class speaker():
    topic = ''
    name = ''
    def __init__(self,n,t):
        self.name = n
        self.topic = t
    def speak(self):
        print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))

#多重继承
class sample(speaker,student):
    a =''
    def __init__(self,n,a,w,g,t):
        student.__init__(self,n,a,w,g)
        speaker.__init__(self,n,t)

test = sample("Tim",25,80,4,"Python")
test.speak()   #方法名同,默认调用的是在括号中排前地父类的方法


#执行以上程序输出结果为:
#我叫 Tim,我是一个演说家,我演讲的主题是 Python

方法重写

  如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法,实例如下:
class Parent: # 定义父类
def myMethod(self):
print (‘调用父类方法’)

class Child(Parent): # 定义子类
   def myMethod(self):
      print ('调用子类方法')

c = Child()          # 子类实例
c.myMethod()         # 子类调用重写方法

# 执行以上程序输出结果为:
# 调用子类方法

1.10.7 多态

- 多态:是指一种事物的多种形态 - 多态性:多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。 - eg:在python中的“+”号,它既可以表示数字的加法,也可以表示字符串的拼接(\_\_add\_\_())

1.10.8 特殊方法与运算符重载

Python类有大量的特殊方法,其中比较常见的是构造函数和析构函数。Python中类的构造函数是\_\_init\_\_(),一般用来为数据成员设置初始值或进行其他必要的初始化工作,在创建对象时被自动调用和执行。 如果用户没有设计构造函数,Python将提供一个默认的构造函数用来进行必要的初始化工作。Python中类的析构函数是\_\_del\_\_(),一般用来释放对象占用的资源,在Python删除对象和收回对象空间时被自动调用和执行。如果用户没有编写析构函数,Python将提供一个默认的析构函数进行必要的清理工作。在Python中,除了构造函数和析构函数之外,还有大量的特殊方法支持更多的功能,例如,运算符重载就是通过在类中里重写特殊函数实现的。在自定义类时如果重写了某个特殊方法即可支持对应的运算符,具体实现什么工作则完全可以根据需要来定义。

类的专有方法:

  • __new___:类的静态方法,用于确定是否要创建对象
  • __init__: 构造函数,在生成对象时调用
  • __del__: 析构函数,释放对象时使用
  • __repr__: 打印,转换
  • __setitem__ : 按照索引赋值
  • __getitem__: 按照索引获取值
  • __len__: 获得长度
  • __cmp__: 比较运算
  • __call__: 函数调用
  • __add__: 加运算
  • __sub__: 减运算
  • __mul__: 乘运算
  • __div__: 除运算
  • __mod__: 求余运算
  • __pow__: 乘方
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值