简介:
Python中也有类的概念,且与所有面向对象语言类似(更类似于java,而不是C++),只是没有public, private, protected关键字。Python使用自己的方法支持这些关键字的功能,但需要用户自己遵守,因为并不是严格支持。
首先,从一个简单的例子学习Python中类的构成:(Python3.3)
class Dog: def __init__(self): self.nr=1# self.nr+=1 is wrong #Dog.nr=111 def __del__(self): pass class Cat: nr=0 def __init__(self): self.nr=9# or self.nr+=9 Cat.nr+=1 dog1=Dog() print(dog1.nr) #print(Dog.nr) cat1=Cat() print("cat1.nr=",cat1.nr,", Cat.nr=",Cat.nr,sep='') cat2=Cat() print("cat2.nr=%d, Cat.nr=%d"%(cat2.nr,Cat.nr))
关于类中出现的的变量,简单的来说,比如在Cat类中,有self.nr与Cat.nr两种,他们的区别是self.nr是类实例的变量,而Cat.nr是类的变量。而在Dog类中由于没有给Dog.nr赋过值,即没有Dog.nr,则在类外面不能使用Dog.nr。同时,另一点需要注意的是:init函数中,如果self.nr是出现在=右边,则要保证其已经被赋过值,或者类名.nr这个变量有值。因为,当遇到+=等操作需要使用self.nr时,如果在函数内未定义过self.nr(即未使用=对self.nr赋过值),则会到函数外面的类变量中进行寻找,如果找到则将类的nr变量的值视为实例自己的nr变量的初值,然后再对类实例自己的nr赋值。以下Dog1是正确的,而Dog2错误:
class Dog1: def __init__(self): Dog.nr=111 self.nr+=1 class Dog2: def __init__(self): self.nr+=1 Dog.nr=111
实际上,类变量的这种情况在继承中也有体现:如果子类中某一变量未被使用=赋过值,则会往上寻找到父类中调用这一变量。
继承,多态:
class Animal: nr=0 def __init__(self): self.nr+=1 Animal.nr+=1 def __del__(self): pass def act(self): print("Act.") def sleep(self): print("Sleep.") class Bird(Animal): def __init__(self): self.nr+=1 Bird.nr+=1 def act(self): print("Fly.") bird1=Bird() print(bird1.nr,Bird.nr) print(bird1.act()) bird1.sleep() bird2=Bird() print(bird2.nr) print(bird1.nr,bird2.nr,Animal.nr,Bird.nr) animal1=Animal() print("Animal.nr=",Animal.nr)
在Bird的init()中,Bird.nr+=1实际上等价于Bird.nr=Animal.nr+1,self.in+=1也等价于self.nr=Animal.nr+1,因为之前未对Bird.nr赋过值,所以在Bird类中找不到nr变量时,会在其父类中查找,如果仍找不到才报错,self.nr同理,只是一个是类的变量,一个是类实例的变量。一旦给Bird.nr赋过值后,Bird.nr就有了自己的值,而不会是Animal.nr。下面这个Bird类,由于始终未对Bird.nr赋值,只是使用了其值,所以Bird.nr实际上一直是Animal.nr,并没有新分配内存来存,可以在改变Animal.nr后查看Animal.nr与Bird.nr进行验证。
class Bird(Animal): def __init__(self): Animal.__init__(self) self.nr=Bird.nr+1 def act(self): print("Fly.",Bird.nr)
私有成员:
Python并没有public, private, protected这些关键字,那么Python如何实现这些功能呢?
实际上,Python使用了自己独特的方法实现的,如果函数名如下任意一种形式,则表示会具有特殊的含义:
_func: 相当于protected func,但只有在某一函数写在类的外面的时候,才不能通过from module import *而被其他模块得到,其他情况均可以被得到。
__func__: 表示系统定义的函数,所以尽量避免使用这种前后各两个下划线的方法定义用户自己的函数。
__func: 相当于private func,但并非绝对的private,会通过下面一个例子解释其原理。
class Parent: def __init__(self): # print('a') self.__act() self.sleep() def __act(self): print("Parent acts.") def sleep(self): print("Parent sleeps.") class Child(Parent): def __act(self): print("Child acts.") def sleep(self): print("Child sleeps.") c=Child()
Parent acts. Child sleeps.
所以,虽然Python提供了一些类似这些关键字的技术,但并非绝对安全,主要还是需要用户自己遵守,不去破坏。