Python面向对象编程详解:类、对象、继承与组合
本文深入解析Python面向对象编程核心,涵盖类与对象的定义、属性与方法区分。详细阐述封装、继承、多态三大特征,解析self机制及__init__等魔法方法。通过代码示例演示私有变量、super()函数应用、组合模式及类与实例对象的内存绑定差异,帮助开发者掌握Python类设计最佳实践。
本文通过具体实例详细解析Python面向对象编程中类与对象的核心概念,旨在帮助读者深入理解并掌握相关技术,供学习参考。
类和对象基础(1)
什么是对象?
对象由属性(静态数据)和方法(动态行为)两部分组成;
属性通常表现为变量,而方法则对应函数定义;
#类的属性即类变量,属于类本身
#实例变量:定义在方法内部的变量,仅在当前实例的类中生效。
具体示例如下:
class Turtle:#python 中类名约定以大写字母开头
'''关于类的简单例子。。。'''
#属性 == 类变量
color ="green"
weight="10kg"
legs=4
shell=True
mouth='big'
#方法
def climb(self):
self.name = "test" #实例变量:定义在方法中的变量,只作用于当前实例的类。
print("我在很努力爬。")
def run(self):
print('我在很努力跑。')
def bite(self):
print('我要要要要要')
def sleep(self):
print('我要睡觉啦。')
#创建一个实例对象也就是类的实例化!
tt =Turtle() #类的实例化,也就是创建一个对象,类名约定大写字母开头
tt.bite() #创建好类后就能调用类里面的方法叻;
tt.sleep()
面向对象编程的主要特征包括:
oo = Object Oriented(面向对象)
1. 封装(信息隐蔽技术)
Python中的列表list本质上是一个对象,它封装了sort()、append()等多种方法;
通过封装,用户可以直接调用内部方法,无需关心具体实现细节;
2. 继承
子类自动共享父类数据和方法的机制,实现代码复用。
class MyList(list):#创建一个类继承list的所有方法和属性 pass #相当于一个占位符 list1=MyList() #类实例化 list1.append(1) #继承后调用list的方法append()
3. 多态
不同对象对同一方法响应不同的行为,即方法名相同但实现不同:
>>> class A:
def fun(self):
print('aaaa')
>>>class B ():
def fun(self):
print('bbb')
>>> a=A()
>>>b=B()
>>>a.fun()
aaaa
>>>b.fun()
bbb
类和对象进阶(2)
self参数的含义?
若将类比作建筑图纸,由类实例化生成的对象则是可居住的房屋。self相当于房屋的门牌号,通过self即可定位到具体的对象实例。
一个类可以生成无数个对象,它们因源自同一类的方法与属性而相似。当对象方法被调用时,Python会将该对象作为第一个参数传递给self,从而确定是哪个对象在调用方法;
>>>class Ball():
def setname(self,name):
self.name=name
def kick (self):
print("我叫%r,谁踢我"%self.name)
>>>a=Ball() 实例化生成a对象
>>>a.setname('a') 调用方法设名为a
>>>b=Ball()
>>>b.setname('b')
>>>c=Ball()
>>>c.setname()
>>>a.kick () 通过self知道是哪个对象调用kick方法
我叫'a',谁踢我
>>>b.kick()
我叫'b',谁踢我
Python中的魔法方法:
__init__(self) 是构造方法。
在实例化对象时,该方法会在对象创建(即实例化类)过程中自动调用。实例化时会自动触发__init__(self)方法。
实例化对象时可传入参数,这些参数会被传入init方法中,通过重写该方法可自定义对象的初始化操作。
>>>class Ball:
def __init__(self,name):
self.name = name
def kick(self):
print('我叫%r,谁踢我'%self.name)
>>> b=Ball('b') #创建对象,这时__init__(self):就被调用了,可以传入b
>>>b.kick()
我叫'b',谁踢我
公有与私有:
Python中对象的属性和方法默认均为公有的,可通过.操作符直接访问。
在Python中定义私有变量,只需在变量名或函数名前增加两个下划线‘__',该函数或变量即变为私有。
>>> class P():
__name="liyue" #私有变量,外部不能通过.操作符直接访问了
类和对象进阶(3):继承
语法结构:
class A(B): ………….
B称为父类、基类或超类;
A称为子类,子类继承父类的属性和方法;
示例代码:
>>> class Parent():
defhello(self):
print("helloliyue!")
>>> class Child(Parent):
pass
>>> p=Parent()
>>> p.hello()
hello liyue!
>>> c=Child()
>>> c.hello()
hello liyue!
注意:若子类中定义了与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性。
具体示例:
>>> class Parent():
defhello(self):
print("helloliyue!")
>>> class Child(Parent):
defhello(self):
print("hahah!")
>>> p=Parent()
>>>p.hello ()
hello liyue!
>>> c =Child()
>>>c.hello () #子类和父类方法相同,(子类重写父类方法)会覆盖父类方法,但是父类自己的方法不变
hahah!
super()函数:解决了子类即使重写父类方法或属性,仍能继续使用父类方法和属性的问题。
具体实例及说明:
import random as r
#利用继承演示鱼游动方向位置。
class Fish(): #父类
def __init__(self):
self.x =r.randint(0,10)
self.y =r.randint(0,10)
def move(self):
self.x -=1 #一直向西移动
print("我的位置是:",self.x,self.y)
classGoldfish(Fish): #子类
pass
classCarp(Fish): #子类
pass
classSalmon(Fish): #子类
pass
classShark(Fish):
def __init__(self): #这里重写了__init__方法,就会覆盖掉父类的方法了,用到super函数后就可以继续使用父类的方法。
#super函数不用给定任何基类的名字(如下),它会一层层找出代码所有父类里面对应的方法,要改变该类的继承关系时只需修改这个类的父类就行就是括号里面的Fish。
super().__init__() #super().重写的属性或方法
self.hungry = True
def eat(self):
if self.hungry:
print("我要吃了。。。")
self.hungry = False
else:
print('好饱了。。。')
>>> f=Fish()
>>>f.move()
我的位置是: -1 3
>>>f.move()
我的位置是: -2 3
>>>g=Goldfish()
>>>g.move()
我的位置是: 4 4
>>>s=Salmon()
>>>s.move()
我的位置是: 8 1
>>>s.move()
我的位置是: 7 1
>>> s=Shark()
>>>s.eat()
我要吃了。。。
>>>s.eat()
好饱了。。。
>>>s.move()
我的位置是: 5 10 #这就是子类就可以使用父类的move()方法
>>>s.move()
我的位置是: 4 10
类和对象进阶(4)
1. 组合:当几个无直接关系的类需要共同使用时,通常通过组合类的方法实现。
示例:要求定义一个水池类,水池中包含乌龟和鱼。
class Turtle(): #定义乌龟类
def __init__(self,x):
self.num = x
classFish(): #定义鱼类
def __init__(self,y):
self.num = y
classPool(): #定义水池类
def __init__(self,x,y):
self.turtle = Turtle(x) #直接把需要的类在这里实例化就行了,组合实现
self.fish = Fish(y)
def print_num(self):
print("水池中总共有乌龟%d只,小鱼%r条。"%(self.turtle.num,self.fish.num)
>>> p =Pool(1,10)
>>>p.print_num ()
水池中总共有乌龟1只,小鱼10条
这就是组合,即将类的实例化放入新类中,从而将旧类组合进去。
组合通常用于处理几个无继承关系、无直接关联的类;若要实现纵向关系,则使用继承。
2. 类、类对象、实例对象

>>>class C(): #类,当类写完后就变成了类对象
def x(self):
print("xaaa")
>>> c =C() #c是实例对象,C()是类对象
>>> c.x()
xaaa
>>> c.x= 1 #实例对象初始化一个变量
>>> c.x
1
>>> c.x() #就不能继续调用原来的方法了,同名会覆盖掉类的方法
Traceback (most recent call last):
File"<pyshell#18>", line 1, in <module>
c.x()
TypeError: 'int' object is not callable
因此:不应试图在一个类中定义所有属性和方法,而应利用继承和组合机制;
建议使用不同词性命名,如属性名用名词,方法名用动词。
3. 什么是绑定?
Python严格要求方法需要有实例才能被调用,这种限制即为绑定。
>>>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仍可调用类对象中的方法:
>>> delCC
>>>dd.setxy (3,4)
>>>dd.__dict__
{'y': 4, 'x': 3}
>>> dd =CC()
Traceback (most recent call last):
File"<pyshell#45>", line 1, in <module>
dd =CC()
NameError: name 'CC' is not defined
>>>dd.printxy ()
3 4
为何已实例化的对象dd仍能调用类对象中的方法?
类中定义的属性是静态变量,方法亦然。即使类对象被删除,属性和方法仍存在于内存中,故实例对象仍可从内存中调用类的方法和属性,除非程序退出。因此,创建类后最好先实例化再使用类对象中的方法,避免直接利用类对象调用方法。
self.x中的self相当于实例对象的名字,.x即实例的空间。
更多关于Python相关内容感兴趣的读者可查看本站专题:《Python面向对象程序设计入门与进阶教程》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python编码操作技巧总结》及《Python入门与进阶经典教程》
希望本文所述对大家Python程序设计有所帮助。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













