Task10:类与对象

mac2026-10-04  1

Task10:类与对象

面向对象技术类对象self代表类的实例,而非类 类的方法私有变量类继承类、类对象和实例对象绑定参考资料

面向对象技术

类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。方法:类中定义的函数。类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。局部变量:定义在方法中的变量,只作用于当前实例的类。实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。实例化:创建一个类的实例,类的具体对象。对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。 Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。 对象可以包含任意数量和类型的数据。

类对象

类对象支持两种操作:属性引用和实例化。 属性引用使用和 Python 中所有的属性引用一样的标准语法:obj.name。 类对象创建后,类命名空间中所有的命名都是有效属性名。

self代表类的实例,而非类

类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。

class Test: def prt(self): print(self) print(self.__class__) t = Test() t.prt() 以上实例执行结果为: <__main__.Test instance at 0x100771878> __main__.Test

从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类。 self 不是 python 关键字,我们把他换成 runoob 也是可以正常执行的。

类的方法

在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例。 在python中定义私有变量只需在变量前加上两个下划线,eg:__name,但是可以通过实例._类名__变量名,同理私有方法。

实例(Python 3.0+) #!/usr/bin/python3 #类定义 class people: #定义基本属性 name = '' age = 0 #定义私有属性,私有属性在类外部无法直接进行访问 __weight = 0 #定义构造方法 def __init__(self,n,a,w): self.name = n self.age = a self.__weight = w def speak(self): print("%s 说: 我 %d 岁。" %(self.name,self.age)) # 实例化类 p = people('runoob',10,30) p.speak() p._people__weight 执行以上程序输出结果为: runoob 说: 我 10 岁。 30

私有变量

默认情况下,Python中的成员函数和成员变量都是公开的(public),在python中没有类似public,private等关键词来修饰成员函数和成员变量。 在python中定义私有变量只需要在变量名或函数名前加上 ”__“两个下划线,那么这个函数或变量就是私有的了。 在内部,python使用一种 name mangling 技术,将 __membername替换成 _classname__membername,也就是说,类的内部定义中, 所有以双下划线开始的名字都被"翻译"成前面加上单下划线和类名的形式。 例如:为了保证不能在class之外访问私有变量,Python会在类的内部自动的把我们定义的__spam私有变量的名字替换成为 _classname__spam(注意,classname前面是一个下划线,spam前是两个下划线),因此,用户在外部访问__spam的时候就会 提示找不到相应的变量。 python中的私有变量和私有方法仍然是可以访问的;访问方法如下: 私有变量:实例._类名__变量名 私有方法:实例._类名__方法名()

其实,Python并没有真正的私有化支持,但可用下划线得到伪私有。 尽量避免定义以下划线开头的变量! (1)_xxx "单下划线 " 开始的成员变量叫做保护变量,意思是只有类实例和子类实例能访问到这些变量, 需通过类提供的接口进行访问;不能用’from module import *'导入 (2)__xxx 类中的私有变量/方法名 (Python的函数也是对象,所以成员方法称为成员变量也行得通。), " 双下划线 " 开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据。 (3)xxx 系统定义名字,前后均有一个“双下划线” 代表python里特殊方法专用的标识,如 init()代表类的构造函数。

类继承

调用父类构造方法 BaseClassName(示例中的基类名)必须与派生类定义在一个作用域内。除了类,还可以用表达式,基类定义在另一个模块中时这一点非常有用: 如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性。

# 类定义 class people: # 定义基本属性 name = '' age = 0 # 定义私有属性,私有属性在类外部无法直接进行访问 __weight = 0 # 定义构造方法 def __init__(self, n, a, w): self.name = n self.age = a self.__weight = w def speak(self): print("%s 说: 我 %d 岁。" % (self.name, self.age)) # 单继承示例 class student(people): grade = '' def __init__(self, n, a, w, g): # 调用父类的构函 people.__init__(self, n, a, w) self.grade = g # 覆写父类的方法 def speak(self): print("%s 说: 我 %d 岁了,我在读 %d 年级" % (self.name, self.age, self.grade)) s = student('小马的程序人生', 10, 60, 3) s.speak() # 小马的程序人生 说: 我 10 岁了,我在读 3 年级

注意:如果上面的程序去掉:people.init(self, n, a, w),则输出:说: 我 0 岁了,我在读 3 年级,因为子类的构造方法把父类的构造方法覆盖了。

类、类对象和实例对象

类对象:创建一个类,其实也是一个对象也在内存开辟了一块空间,称为类对象,类对象只有一个。 实例对象:就是通过实例化类创建的对象,称为实例对象,实例对象可以有多个。 类属性:类里面方法外面定义的变量称为类属性。类属性所属于类对象并且多个实例对象之间共享同一个类属性,说白了就是类属性所有的通过该类实例化的对象都能共享。

class A(): a = xx #类属性 def __init__(self): A.a = xx #使用类属性可以通过 (类名.类属性)调用。

实例属性:实例属性和具体的某个实例对象有关系,并且一个实例对象和另外一个实例对象是不共享属性的,说白了实例属性只能在自己的对象里面使用,其他的对象不能直接使用,因为self是谁调用,它的值就属于该对象。

class 类名(): __init__(self): self.name = xx #实例属性

类属性和实例属性区别

类属性:类外面,可以通过实例对象.类属性和类名.类属性进行调用。类里面,通过self.类属性和类名.类属性进行调用。实例属性 :类外面,可以通过实例对象.实例属性调用。类里面,通过self.实例属性调用。实例属性就相当于局部变量。出了这个类或者这个类的实例对象,就没有作用了。类属性就相当于类里面的全局变量,可以和这个类的所有实例对象共享 # 创建类对象 class Test(object): class_attr = 100 # 类属性 def __init__(self): self.sl_attr = 100 # 实例属性 def func(self): print('类对象.类属性的值:', Test.class_attr) # 调用类属性 print('self.类属性的值', self.class_attr) # 相当于把类属性 变成实例属性 print('self.实例属性的值', self.sl_attr) # 调用实例属性 a = Test() a.func() # 类对象.类属性的值: 100 # self.类属性的值 100 # self.实例属性的值 100 b = Test() b.func() # 类对象.类属性的值: 100 # self.类属性的值 100 # self.实例属性的值 100 a.class_attr = 200 a.sl_attr = 200 a.func() # 类对象.类属性的值: 100 # self.类属性的值 200 # self.实例属性的值 200 b.func() # 类对象.类属性的值: 100 # self.类属性的值 100 # self.实例属性的值 100 Test.class_attr = 300 a.func() # 类对象.类属性的值: 300 # self.类属性的值 200 # self.实例属性的值 200 b.func() # 类对象.类属性的值: 300 # self.类属性的值 300 # self.实例属性的值 100

注意:属性与方法名相同,属性会覆盖方法

class A: def x(self): print('x_man') aa = A() aa.x() # x_man aa.x = 1 print(aa.x) # 1 aa.x() # TypeError: 'int' object is not callable

绑定

python严格要求方法需要有实例才能被调用,这种限制其实就是绑定。

class BB: def printBB(): print("BB") BB.printBB() bb = BB() bb.printBB() class BB: def printBB(): print("BB") BB.printBB() bb = BB() bb.printBB()

这个例子告诉我们,bb.printBB()实际执行的是bb.printBB(bb)。所以方法中需要加入self这个绑定实例对象。

>>>class CC: #类 def setxy(self,x,y): self.x = x self.y = y def printxy(self): print(self.x,self.y) >>> dd= CC() #实例对象,类对象 >>>dd.__dict__ #查看实例对象所拥有的属性 {} >>>CC.__dict__ #查看类对象所拥有的属性 mappingproxy({'setxy':<function CC.setxy at 0x00000000031F9B70>, 'printxy': <functionCC.printxy at 0x00000000031F9BF8>, '__module__': '__main__', '__weakref__':<attribute '__weakref__' of 'CC' objects>, '__dict__': <attribute '__dict__'of 'CC' objects>, '__doc__': None}) >>>dd.setxy (4,5) #实例对象中传入x,y >>>dd.__dict__ #实例对象就有属性了,这两个属性紧属于实例对象的,类对象中是没有的 {'y': 5, 'x': 4} #类对象中是没有实例对象传入的,这归功与绑定这个功能,self

为什么实例对象调用方法后类对象中没有实例对象的属性? 实例对象调用方法时,dd.setxy(dd,4,5) 实际上是这样的,也就是(self.x = x;self.y = y)dd.x=4,dd.y=5,那么4,5存放在实例对象的空间,故这两个属性只属于实例对象的。(实例对象调用类方法时,先把自己传给self,self.x也就是dd.x.) 类对象与实例对象差别: 把类对象CC删除后,del CC,再实例化就会报错,但是已经实例化对象dd仍然可以调用类对象中的方法 为什么已经实例化对象dd仍然可以调用类对象中的方法? 类中定义的属性是静态变量,方法也一样,就算类对象被删除了,属性和方法一样存放在内存中,故实例对象仍然可以从内存中调用类的方法和属性,除非程序退出。所以创建一个类后最好先实例化再使用类对象中的方法,不要直接利用类对象调用方法。 self.x self相当于实例对象的名字,.x就是实例的空间了

参考资料

LSGOGroup 老马的程序人生FishC.comRunoob.comhttps://blog.csdn.net/qq_40946639/article/details/102673760https://www.jb51.net/article/152398.htm
最新回复(0)