目录
写在前面
Python中的面向对象和c++、java中的面向对象非常类似,也具有继承、封装、多态等特性。但是Python中的类有所不同,在Python中,类也是对象,是type类型的对象,也分配有一块内存,这点与c++、java不同。Python中的类也可以进行一系列访问操作,而不是像c++、java那样简单的抽象。
所以类中的变量和实例中的变量是不同的、各管各的。修改了类变量之后,已经创建了的实例中的变量不会被修改,但是会影响之后创建的实例。
类的定义
定义一个类的基本格式为:
class 类名([父类]):
公共的属性
对象的初始化方法
def __init__(self,...):
其他的方法
def method_1(self,...)
def method_2(self,...)
例如:
>>> class a:
... def fun(self):
... print("123")
Python的类中定义一个方法必须默认传递一个参数(当前对象self)
类的初始化
类创建一个对象的流程是:先创建一个变量、然后再内存中创建一个新对象、执行特殊方法、将对象的id赋给变量。特殊方法是以双下划线开头、双下划线结尾的函数例如:__init__(),特殊方法会在特殊时刻自动调用。__init__会在对象创建时给类初始化一些属性。例如:
>>> class a:
... def __init__(self,name):
... self.name=name
...
>>> b=a("小明")
>>> print(b.name)
小明
类的封装
封装就是把类的属性隐藏起来,只能通过一些方法来访问或者修改。首先将属性设为私有类型,然后为这个属性设置set和get方法,最后限制这些set和get方法的使用。
在Python中设置私有属性的方法大致有两种:一种是在变量名前加两个下划线_,没有特殊需要不要修改,实际可以修改。另一种用装饰器。这种方法与java中的类似,通过装饰器使get方法可以像属性一样被调用。例如:
>>> class person2:
... def __init__(self,name):
... self.__name=name
... # get方法 #
... @property
... def name(self):
... return self.__name
... @name.setter
... def name(self,name):
... self.__name=name
...
>>> xiaoming=person2("小明")
>>> print(xiaoming.name)
小明
>>> xiaoming.name="明明"
>>> print(xiaoming.name)
明明
类的继承
Python中的继承与c++、java基本保持一致,一个类继承了父类之后,就获得了父类的所有属性和方法,也可以重写父类的方法。例如:
>>> class animal:
... def __init__(self,name):
... self.name=name
... def run(self):
... print("%s会跑"%self.name)
... def sleep(self):
... print("%s会睡觉"%self.name)
...
>>> class dog(animal):
... def run(self):
... print("狗会跑")
... super(dog, self).run()
... def bark(self):
... print("汪汪汪")
...
>>> d=dog("狗")
>>> d.run()
狗会跑
狗会跑
其中super函数可以在子类中获取父类的属性和方法。也可以继承多个父类,若多个父类中都定义了相同名字的方法,则会按定义的顺序从弗雷中寻找,找到第一个执行。
类中的属性
类属性
如果直接在定义类时,在类中定义了一些变量,那么这些变量就是类属性,可以通过类和类的实例访问到,但是不能被实例修改,只能由类来修改。此时类和它的实例分别具有一块内存,互不干扰。例如:
>>> class a:
... i=10
...
>>> b=a()
>>> b.i=100
>>> print(b.i,a.i)
100 10
>>> print(id(a),id(b))
37112168 37951824
实例属性
实例属性是由实例对象添加的属性,只能由实例来修改。例如:
>>> class a:
... def __init__(self,name):
... self.name=name
...
>>> b=a("1")
>>> print(b.name)
1
>>> print(a.name)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'a' has no attribute 'name'
上面我定义了一个a类,其中的__init__方法添加了name属性,这个属性只能被实例b调用,不能被类a调用。
类中的方法
实例方法
所有在类中定义的,并且以self为第一个形参的方法都是实例方法。实例方法可以被实例直接调用。但是如果类要调用实例方法的话,需要在参数里加上一个这个类的实例名。例如:
>>> class a:
... def test(self):
... print("实例方法")
...
>>> b=a()
>>> b.test()
实例方法
>>> a.test(b)
实例方法
在上面我定义了一个类a,里面的test就是实例方法。然后创建了一个对象b,b可以直接调用实例方法。但是类a想调用实例方法必须在参数列表里加上a类的一个对象b。
类方法
在函数之前加上@classmethod,并且第一个参数为cls的方法为类方法。类和实例都可以调用,调用方法没有区别。例如:
>>> class a:
... @classmethod
... def test_2(cls):
... print("这是个类方法")
...
>>> b=a()
>>> b.test_2()
这是个类方法
>>> a.test_2()
这是个类方法
静态方法
Python中的静态方法和类方法很相似,如果不把cls当做第一个形参的话, 这个方法就是静态方法。同时,与类方法类似,我们需要使用staticmethod函数将这个函数转换成真正的静态方法。
>>> class a:
... @staticmethod
... def test_3(a):
... print("静态方法",a)
...
>>> b=a()
>>> a.test_3("1")
静态方法 1
>>> b.test_3("1")
静态方法 1
静态方法和类方法的作用也很相似。因为在类方法中的第一个参数是实例,因此,我们可以在函数中使用这个引用。也就是说,当我们需要使用类的引用的时候我们需要使用类方法。不需要使用类的引用的时候则可以使用静态方法。
我是Python的初学者,一些地方可能写的不够清晰,错误请指正。