Python面向对象(一)类与对象

类的定义

语法格式:

class 类名(继承类):
    (>=0)个类属性...
    (>=0)个类方法...

其中类属性指的是包含在类中的变量(对照C++成员),类方法指的是包含在类中的函数(对照C++成员函数),类属性和类方法的顺序可以任意调换

实例:

class MyClass:
    '''
    自己定义的一个类
    '''
    # 定义一个类方法
    def printInfo(self,info):
        print("MyClass:",info)
    # 定义一个类属性
    defaultInfo="Default Info"

self

在定义类的过程中,无论是显式创建类的构造方法,还是向类中添加实例方法,都要求将 self 参数作为方法的第一个参数。self参数有点类似C++中的this指针。

同一个类可以产生多个实例化对象,当某个对象调用类方法时,该对象会将自身的引用作为第一个参数自动传递到该方法上,如此Python解释器就知道要操作哪个对象的方法了。

>>> class MyClass:
	def lookSelf(self):
		print(self)

>>> c= MyClass()
>>> c.lookSelf()
<__main__.MyClass object at 0x000002811B94C4F0> 
>>> d= c.lookSelf
>>> d()
<__main__.MyClass object at 0x000002811B94C4F0> #同一对象
>>> 

类的实例化

实例化后的类对象可以执行以下操作:

  • 访问或修改类对象具有的实例变量,也可以添加新的实例变量或删除旧的实例变量,如果新添的实例变量与类中的方法重名,则会顶替掉类方法
  • 调用类对象的方法,也可以给类对象动态添加方法,若位类对象动态添加方法,需要手动添加self属性将其绑定到第一个参数上

类属性和实例属性

根据变量定义的位置不同以及定义的方式不同,类属性可以分为以下三种:

  • 类属性/类变量:类体中、所有函数之外
  • 实例属性/实例变量:类体中,所有函数内部,且以self.变量名的方式定义的变量
  • 局部变量:类体中,所有函数内部,且以变量名 = 变量值定义的变量

类变量/类属性

对于类属性/类变量,所有类的实例化对象都同时共享类变量,类变量在所有实例化对象中是作为共有资源存在的,可以通过类名.类变量调用,也可以通过实例化对象.类变量调用。因此,通过类名修改类变量会影响所有实例化对象:

>>> class MyClass():
	var =10 #类变量
	
>>> MyClass.var
10
>>> a=MyClass() # 实例化对象a
>>> b=MyClass() # 实例化对象b
>>> a.var
10
>>> b.var
10
>>> a.var=12    # 相当于定义新的实例变量
>>> b.var   # 不影响b
10
>>> MyClass.var=15  # 通过类名修改类变量
>>> a.var   # a的var现在是新的实例变量
12
>>> b.var   # b作为MyClass的实例化对象,受影响
15
>>> #同理,也可以动态地为类和对象添加类变量

实例属性/实例变量

对于实例属性/实例变量,其特点是只作用于调用方法的对象,同时也只能通过对象名访问,无法通过类名访问。上面的例子提到,无法通过类对象修改类变量,本质是新添实例变量

>>> class MyClass():
	varA=10
	def getVarB(self):
		self.varB=20

		
>>> c=MyClass()
>>> c.varA  # 类变量varA
10
>>> c.varB  # 实例变量varB
Traceback (most recent call last):
  File "<pyshell#76>", line 1, in <module>
    c.varB
AttributeError: 'MyClass' object has no attribute 'varB'
>>> c.getVarB() # 调用getVarB()后才存在varB
>>> c.varB
20
>>> 

局部变量

对于局部变量,局部变量直接以“变量名=值”的方式进行定义,局部变量只能用于所在函数中,函数执行完成后,局部变量也会被销毁。

_slots_限定绑定

Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:

>>> class Student(object):
    __slots__ = ('name','age')  # 用tuple定义允许动态绑定的变量名

    
>>> student = Student()
>>> student.name='A'
>>> student.age=18
>>> student.score=95
Traceback (most recent call last):
  File "<pyshell#47>", line 1, in <module>
    student.score=95
AttributeError: 'Student' object has no attribute 'score'
>>> 

实例方法、静态方法和类方法

类方法可以区分为实例方法、静态方法和类方法,采用@classmethod修饰的方法就是类方法,采用@staticmethod修饰的就是静态方法,不使用任何修饰的就是实例方法。

实例方法

通常情况下,Python中的方法默认都是实例方法,实例方法最少需要一个self参数,用于绑定调用此方法的实例对象,实例方法可以由实例对象直接调用(不需要显示传入self参数),也可以用类名调用实例方法,但需要手动传入self参数:

>>> MyClass.getVarB(c)
>>> class MyClass():
	def MyMethod(self):
		print("调用MyMethod()")

		
>>> c=MyClass()
>>> c.MyMethod()
调用MyMethod()
>>> MyClass.MyMethod(c) #手动传参
调用MyMethod()
>>> 

类方法

类方法与实例方法类似,都需要至少一个参数,通常命名为cls而不是self(习惯问题),Python会自动将类本身绑定给cls参数,利用类名调用类方法时,无需显示地为cls传参。

>>> class MyClass():
	@classmethod
	def MyClassMethod(cls):
		print("调用MyClassMehod()")

		
>>> MyClass.MyClassMethod() #   无需显式传参
调用MyClassMehod()
>>> c=MyClass
>>> c.MyClassMethod()   # 也可以利用实例化对象调用,但是不推荐
调用MyClassMehod()
>>> 

静态方法

静态方法实际上就是定义在类内部的函数,与函数的区别就是静态方法定义在类命名空间中,而普通的函数定义在全局命名空间中。静态方法采用关键字@staticmethod

由于静态方法无需self 或 cls 参数,因此 Python 解释器不会对它包含的参数做任何类或对象的绑定,即类的静态方法无法调用任何类方法和类属性。静态方法的调用既可以使用类名,也可以使用类对象。

在实际编程中,几乎不会用到类方法和静态方法,因为我们完全可以使用函数代替它们实现想要的功能,但是在工厂模式中时不错的选择。

posted @ 2020-09-12 16:43  海物chinono  阅读(190)  评论(0)    收藏  举报