Python 面向对象编程
python是一门解释语音,但是它是面向对象的,可以进行对象编程。在进行python面向对象编程之前,先来了解几个术语:类、类对象、实例对象、属性、函数和方法。
一、如何定义一个类?
class people(object): #新式类 block class people: #经典类 block
类后面有个冒号,在block块里面可以定义属性和方法。当一个类定义完就产生了一个类对象。类对象支持两种操作:实例化和引用。引用操作就是通过类对象去调用类中的函数和方法,而实例化则是产生一个类对象的实例,称作实例对象:
class human(object): #定义一个新式类human sex = 'male' #定义一个属性 def func(self): #定义一个方法 print(self.sex)
human类定义完成后就产生了一个全局的类对象,可以通过类对象访问类中的属性和方法。当通过human.sex来访问时,human.sex中的human就称为类对象。也可以进行实例化操作,h=human(),这样就产生了一个human的实例对象,此时也可以通过对象H来访问属性和方法h.sex
了解了类、类对象和实例对象的区别后,我们继续了解python中的函数、方法和属性的区别。
在上面的代码中注释中,我们知道sex是一个属性,func()是一个方法,与某个对象进行绑定的函数叫做方法。在类中定义的函数与类对象或者实例对象绑定了,所以称作方法。而类外定义的函数一般没有进行绑定,就称作函数。
二、属性
在类中,我们可以定义一些属性,比如:
class animal(object): name = 'dog' age = 2 a = animal() print(a.name,a.age)
定义一个animal类,里面定义了name和age属性。在定义类之后,就可以来产生实例化对象,a = animal()就产生了一个实例化对象a,这里name和age都是公有属性,可以在类外直接通过对象名访问,如果想定义成私有的,就在属性前面加上两个下划线'__'
class animal(object): __name = 'dog' __age = 2 a = animal() print(a.__name,a.__age)
这段程序会报错
Traceback (most recent call last): File "C:/Users/PycharmProjects/untitled1/file.py", line 8, in <module> print(a.__name, a.__age) AttributeError: 'animal' object has no attribute '__name'
提示找不到该属性,因为私有属性是不能够在类外通过对象名进行访问的,在python里面没有public和private关键字来区别公有属性和私有属性,它是以属性命名方式来区分的,如果在属性名前面加2个下划线'__',则表明该属性为私有属性,否则为公有属性(方法同属性一样,也是前面加2个下划线'__')
三、方法
在类中可以根据需要定义一些方法,定义方法采用def关键字,在类中定义的方法至少会有一个参数,一般以名为'self'的变量作为该参数,而且作为第一个参数。下面来看个例子:
class human(object): __name = 'Jack' __age = 24 def getname(self): return self.__name def getage(self): return self.__age m = human() print(m.getname()) print(m.getage())
四、类中内置的方法
在Python中有一些内置的方法,这些方法命名都有比较特殊的地方(其方法名以2个下划线开始然后以2个下划线结束)。类中最常用的就是构造方法和析构方法。
构造方法__init__(self,....)在生成对象时调用,可以用来进行一些初始化操作,不需要显示去调用,系统会默认去执行。构造方法支持重载,如果用户自己没有重新定义构造方法,系统就自动执行默认的构造方法。
析构方法__del__(self)在释放对象时调用,支持重载,可以在里面进行一些释放资源的操作,不需要显示调用。
五.类属性、实例属性、类方法、实例方法以及静态方法
了解一些基本概念后,我们来学学python中这几个概念的区别。
在前面的例子中,我们接触到的就是类属性,顾名思义,就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存一个副本,这个和c++中类的静态成员变量有些类似。对于公有的类属性,可以通过类对象和实例对象调访问。
class people(object): name = 'TOM' #公有类属性 __age = 18 #私有类属性 p = people() print(p.name) print((people.name)) print(p.__age) print(people.__age)
实例属性是不需要在类中显示定义的。
class animal(object): name = 'cat' a = animal() a.sex = 'male' print(a.name) #正确 print(a.sex) #正确 print(animal.name) #正确 print(animal.sex) #错误
在类外对类对象people进行实例化之后,产生了一个实例对象p,然后p.age = 12这句给p添加了一个实例属性age,赋值为12。这个实例属性是实例对象p所特有的,注意,类对象people并不拥有它(所以不能通过类对象来访问这个age属性)。当然还可以在实例化对象的时候给age赋值。
class people(object): name = 'jack' #__init__()是内置的构造方法,在实例化对象时自动调用 def __init__(self,age): self.age = age p = people(12) print (p.name) #正确 print (p.age) #正确 print (people.name) #正确 print (people.age) #错误
如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。
class people(object): country = 'china' print (people.country) p = people() print (p.country) p.country = 'japan' print (p.country) #实例属性会屏蔽掉同名的类属性 print (people.country) del p.country #删除实例属性 print (p.country)
运行结果:
china
china
japan
china
china
下面来看下类方法、实例方法和静态方法的区别。
类方法:类对象所拥有的方法,需要用修饰器"@classmethod"来标识其为类方法。对于类方法,第一个参数必须为类对象,已办以"cls"作为第一个参数(当然也可以用其他名称的变量作为第一个参数,但习惯以"cls"为第一个参数),可以通过实例对象和类对象去访问。
class Country(object): name = 'china' # 类方法,用classmethod来标识 @classmethod def getprovince(cls): return cls.name c = Country() print(c.getprovince()) print(Country.getprovince())
类方法还有一个用途就是可以对类属性进行修改:
class people(object): country = 'china' #类方法,用classmethod来进行修饰 @classmethod def getCountry(cls): return cls.country @classmethod def setCountry(cls,country): cls.country = country p = people() print (p.getCountry()) #可以用过实例对象引用 print (people.getCountry()) #可以通过类对象引用 p.setCountry('Italy') print (p.getCountry()) print (people.getCountry())
运行结果:
china
china
Italy
Italy
运行结果显示在使用类方法实例对象对类属性修改之后,通过类对象和实例对象访问都发生改变。
实例方法:在类中最常定义的成员方法,它至少有一个参数并且必须以实例对象作为其第一个参数,一般以名为'self'的变量作为第一个参数(当然可以以其他名称的变量作为第一个参数)。在类外实例方法只能通过实例对象去调用,不能通过其他方式去调用。
class people: country = 'china' #实例方法 def getCountry(self): return self.country p = people() print (p.getCountry()) #正确,可以用过实例对象引用 print (people.getCountry()) #错误,不能通过类对象引用实例方法
静态方法:需要通过修饰器"@staticmethod"来进行修饰,静态方法不需要多定义参数。
class people(object): country = 'china' @staticmethod #静态方法 def getCountry(): return people.country print (people.getCountry())
从类方法和实例方法以及静态方法的定义形式就可以看出来,类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法;而实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类对象来引用。