标签:前缀 参数 利用 一个 nbsp 完成 soft 任务 init
Python不仅支持面向过程编程,同时也支持面向对象编程。面向工程就是分析解决问题所需的步骤,然后用函数把这些步骤逐一实现,使用的时候再一个个调用函数就可以。面向对象则是把解决的问题按照一定规则划分为多个独立的对象,然后通过调用对象的方法来解决问题。在编写小程序(少于500行代码)时,使用面向过程编程基本上不会有任何问题。但对于中等和大型项目来说,面向对象将给代码的编写和维护带来很多优势。本文主要介绍Python中面向对象的基本概念。
面向对象的特点主要可以概括为封装性、继承性、多态性。
(1)封装性
封装是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体实现细节,这就是封装的思想。比如,用户使用电脑,只需要会敲键盘就可以,无须知道电脑内部是如何工作的。
(2)继承性
继承性主要描述的是类与类之间的关系,通过继承,可以在无须重新编写原有类的情况下,对原有类的功能进行扩展。
(3)多态性
多态性指的是在程序中允许重名现象,它指在一个类中定义的属性和方法被其他类继承后,它们可以具有不同的数据类型或表现出不同的行为,这使得同一个属性和方法在不同的类中具有不同的语义。
面向对象的思想需要通过大量的实践去学习和理解,才能将面向对象真正理解清楚。后面会通过一些例子介绍其使用方法。
面向对象的思想中提出了两个概念,即类和对象。类是对某一类事物的抽象描述,是一种抽象的数据类型,一种模板。而对象用于表示现实中该类事物的个体,也就是具体化了类的描述。它们的关系是,对象是类的具体实例,类是对象的模板。对象根据类创建,一个类可以创建多个对象。比如我定义了一个学生类,那么通过类创建出来的小明、小王就叫对象。
在面向对象的思想中最核心的就是对象,在程序中创建对象,首先需要定义一个类。Python中使用class关键字定义一个类,类的主体由属性(变量)和方法(函数)组成。通过定义一个水果类来看下类的定义格式,如下:
#-*- coding:utf-8 -*- #类的创建 class Fruit(object): def __init__(self, name, color): #__init__为类的构造函数 self.name = name #实例变量 self.color = color #实例变量 def grow(self): #grow函数为实例方法。类的函数至少有1个self参数 print "Fruit grow..."
其中,Fruit是类名,类名的首字母一般是大写。price变量在实例方法和构造方法之外,称为类属性。__init__(self)是构造函数,构造函数中的name和color变量称为实例属性,grow(self)是实例方法,实例方法中参数至少带一个self参数。
定义完类之后,就可以根据类来创建实例对象,创建对象的过程称为实例化。当一个对象被创建后,包含3个方面的特性:对象的句柄、属性和方法。对象的句柄用于区分不同的对象,当对象被创建后,该对象会获取一块存储空间,存储空间的地址即为对象的标识。对象的属性和方法与类的成员变量和成员函数相对应。Python实例化是通过类名加圆括号的方式。实例化上述定义的水果类,格式如下:
#-*- coding:utf-8 -*- class Fruit(object):def __init__(self, name, color): #构造函数 self.name = name #实例变量 self.color = color #实例变量 def grow(self): print "Fruit grow..." if __name__ == ‘__main__‘: apple = Fruit(‘apple‘,‘red‘) #实例化对象apple print apple.name # 利用对象直接获取对象属性name。输出apple print apple.color # 利用对象直接获取对象属性color。输出red apple.grow() # 利用对象直接调用对象方法,不需要给参数self赋值。输出Fruit grow...
实例化对象之后,就可以通过对象直接调用对象的属性和方法。但是注意的是对象调用方法时,不需要给参数self赋值,self参数用于表示指向实例对象本身。到这里,已经学会了类的定义和对象创建方法和使用了。上述的例子中仅介绍了类的基本实例属性和实例方法的定义,实际上实例变量还区私有属性和公有属性,还有类变量等概念。类中的方法还包括静态方法、类方法。
类的属性是对数据的封装,类的属性包括实例属性、类属性两种。实例属性又区分为实例私有属性和实例公有属性。不同的属性类型调用方法也不同。
(1)实例私有属性和实例公有属性
实例属性一般分为私有属性和公有属性,不同于Java、C++等语言通过使用保护类型的修饰符去区分私有属性和公有属性,由于Python没有保护类型的修饰符,Python类的私有属性和共有属性是通过约定属性名称来达到数据封装的目的。如果属性的名字以两个下划线开始,就表示为私有属性。反之,则表示公有属性。
#-*- coding:utf-8 -*- class Fruit(object): def __init__(self, name, color): self.__name = name #实例私有变量使用双下划綫开始 self.color = color def grow(self): print "Fruit grow..." if __name__ == ‘__main__‘: apple = Fruit(‘apple‘,‘red‘) #实例化水果类 #print apple.__name #不能直接报错AttributeError: ‘Fruit‘ object has no attribute ‘__name‘ print apple._Fruit__name #apple print apple.color #red
实例的私有属性不能使用实例直接访问,Python解释器会报错提示属性不存在。Python提供了直接访问私有属性的方式,可用于程序的测试和调试。私有属性访问的格式如下所示:
instance._classname__attribute
也就是实例名._类名__属性名的方式。如例子中的apple._Fruit__name。但是这种直接暴露数据的做法是不提倡的。因为这种方式可以随意更改实例属性的值,会导致程序数据安全方面的问题。这种访问方式主要用于开发阶段的测试或调试时使用。通过的做法是定义相关的get方法获取实例属性的值。例如在Fruit类中定义getColor()方法,后续会介绍方法的定义和使用。
(2)实例属性和函数变量
Python的属性分为实例属性和静态属性。实例属性是以self作为前缀的属性。__init__方法即Python类的构造函数。如果__init__方法中定义的变量没有使用self作为前缀声明,则该变量只是普通的局部变量。类中其他方法定义的变量也只是函数变量,而非类的实例属性。
#-*- coding:utf-8 -*- class Fruit(object): def __init__(self, name, color, zone): self.__name = name #name、color变量加前缀self表示实例属性,可以被实例化对象调用 self.color = color zone = zone #zone变量不加前缀self,只是普通的函数变量,不能被实例化对象调用 def grow(self): print "Fruit grow..." if __name__ == ‘__main__‘: apple = Fruit(‘apple‘,‘red‘, ‘Shannxi‘) #实例化水果类 print apple._Fruit__name #apple print apple.color # red #print apple.zone # 报错AttributeError: ‘Fruit‘ object has no attribute ‘zone‘
例子中定义的函数变量zone不能被Fruit的实例化对象调用。
(2)类变量
Java、C#中有一类特殊的属性称为静态变量。静态变量可以被类直接调用,而不被实例化对象调用。当创建新的实例化对象后,静态变量并不会获得新的内存空间,而是使用类创建的内存空间。因此,静态变量能够被多个实例化对象共享。在Python中静态变量称为类变量,类变量可以在该类的所有实例中被共享。
#-*- coding:utf-8 -*- class Fruit(object): price = 0 #类变量 def __init__(self, name, color, zone): self.__name = name #name、color变量加前缀self表示实例属性,可以被实例化对象调用 self.color = color zone = zone #zone变量不加前缀self,只是普通的变量,不能被实例化对象调用 def grow(self): print "Fruit grow..." if __name__ == ‘__main__‘: apple = Fruit(‘apple‘,‘red‘, ‘Shannxi‘) #实例化水果类 print Fruit.price # 0 Fruit.price = Fruit.price + 100 print "apple‘s prices = %d" % (apple.price) #100 banana = Fruit(‘banana‘, ‘yellow‘, ‘Hainan‘) print "banana‘s prices = %d" % (banana.price) #100 apple.price = 150 #修改apple对象中price的值,与banana对象无关。 print "apple‘s prices = %d" % (apple.price) #150 print "banana‘s prices = %d" % (banana.price) #100 banana.price = 200 #修改banana对象中price的值,与apple对象无关 print "apple‘s prices = %d" % (apple.price) #150 print "banana‘s prices = %d" % (banana.price) #200 Fruit.price = Fruit.price + 100 #使用类调用修改price值,不影响apple、banana对象中price的值 print "apple‘s prices = %d" % (apple.price) #150 print "banana‘s prices = %d" % (banana.price) #200 print Fruit.price #200
Python对象类的属性和方法定义次序并没有要求。合理的方式是把类属性定义在类中最前面,然后再定义私有方法,最后定义公有方法。
(1)普通方法和静态方法
类的方法也分为公有方法和私有方法。私有方法不能被模块外的类或方法调用,私有方法也不能被外部的类或函数调用。C#、Java中的静态方法使用关键字static声明,而Python使用函数staticmethod()或@staticmethod修改器把普通的函数转换为静态方法。Python的静态方法并没有和类的实例进行绑定,要调用只需使用类名作为它的前缀即可。下面这段代码演示了类的方法和静态方法的使用。
#-*- coding:utf-8 -*- class Fruit(object): price = 100 #类属性 def __init__(self, name, color, zone): self.__name = name self.color = color def getColor(self): print self.color def getName(self): print self.__name def setColor(self, color): self.color = color def setName(self, name): self.__name = name @staticmethod #方法一,定义类的静态方法,调用类变量,getPrice中不带self参数 def getPrice(): print Fruit.price def getPrice2(): print Fruit.price tran_getPrice2 = staticmethod(getPrice2) ##方法二,定义类的静态方法,调用类变量 if __name__ == ‘__main__‘: apple = Fruit(‘apple‘,‘red‘, ‘Shannxi‘) #实例化水果类 apple.getColor() # red apple.getName() #apple apple.setColor(‘green‘) apple.getColor() #green apple.setName(‘new_apple‘) apple.getName() #new_apple Fruit.getPrice() Fruit.tran_getPrice2()
上述代码中getColor()方法中有1个self参数,该参数是区别方法和函数的标志。类的方法至少需要1个参数,调用方法时不必给改参数赋值。通过长这个特殊的参数被命名为self,self参数表示指向实例对象本身。self参数用于区分函数和类的方法。self参数等价于Java、C#中的this关键字,但self必须显示使用,因为Python是动态语言,没有提供声明变量的方式,这样就无法知道在方法中要赋值的变量是不是局部变量或是否需要保存成实例属性。当调用Fruit类的getColor()方法时,Python会把函数的调用转换为grow(fruit)。Python自动完成了对象fruit的传递任务。
(2)类方法
Python中还有一种方法称为类方法。类方法是将类本身作为操作对象的方法。类方法可以使用函数classmethod()或@classmethod修饰器定义。而与实力方法不同的是,把类作为第一个参数(cls)传递。把上述程序的静态方法修改为类方法,修改后的代码如下:
@classmethod #方法一,定义类方法,调用类变量,getPrice中不带self参数 def getPrice(cls): print cls.price def getPrice2(cls): print cls.price tran_getPrice2 = classmethod(getPrice2) ##方法二,定义类方法,调用类变量
可见,类方法的使用和静态方法十分相似。如果某个方法需要被其他实例共享,同时又需要使用当前实例的属性,则定义为类方法。
标签:前缀 参数 利用 一个 nbsp 完成 soft 任务 init
原文地址:https://www.cnblogs.com/linyfeng/p/9185785.html