Python3之类和实例
面向对象的重要概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如学生类Student,而实例是根据类创建出来的一个个具体的对象,每个对象都拥有相同的方法,单各自的数据可能不同。
以Student为列,在Python中,定义类是通过class关键字
1 2 | >>> class Student( object ): ... pass |
class关键字后面紧接是类名,即Student,类名通常是大小字母开头,紧接着是(object),表示该类从哪个类继承下来,通常没有合适的继承类,就使用object类,这是使用类最终都会继承的类
定义好了Student类,就可以根据Student类创建出Student实例,创建实例通过类名+()实现
1 2 3 4 5 6 7 | >>> bart = Student() >>> bart # bart指向就是一个Student的实例0x7ffbd69f7a20为实例的内存地址 <__main__.Student object at 0x7ffbd69f7a20 > >>> Student #表示Student是一个类class < class '__main__.Student' > |
可以自由地给实例变量绑定属性,比如,给实例bart绑定一个name属性
>>> bart.name = 'Zhang San' >>> bart.name 'Zhang San' |
由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__方法,在创建实例的时候就把name,score等属性绑上去
1 2 3 4 | class Student( object ): def __init__( self ,name,score): self .name = name self .score = score |
PS:特殊方法__init__前后分别有两个下划线
__init__方法是第一个参数永远是self,表示创建实例的本身,因此在__init__方法内部,就可以把各种属性绑定到self,因为self执行创建实例的本身
有了__init__方法,在创建实例的时候就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去
1 2 3 4 5 | >>> bart = Student( 'ZhangSan' , 59 ) >>> bart.name 'ZhangSan' >>> bart.score 59 |
为查看self是否是实例本身在类里面增加一个print打印self然后在外部创建实例的时候打印一下实例本身看内存地址是否相同
1 2 3 4 5 6 7 | class Student( object ): def __init__( self ,name,score): self .name = name self .score = score print ( '类内部打印实例' , self ) bart = Student( 'Zhang San' , 59 ) print ( '类外部打印实例' ,bart) |
运行结果,内存地址是相同的
1 2 | 类内部打印实例 <__main__.Student object at 0x7f250da8a630 > 类外部打印实例 <__main__.Student object at 0x7f250da8a630 > |
和普通函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时不用传递该参数。除此以外,类方法和普通函数没有什么区别,所以,仍然可以使用默认参数,可变参数,关键字参数和命名关键字参数。
数据封装
面向对象编程的一个重要特点就是数据封装。在上面的Student类中,每个实例就拥有各自的name和score这些数据。我们可以通过函数来访问这些数据,比如打印一个学生的名字和成绩
1 2 3 4 5 | >>> def print_score(std): ... print ( '%s:%s' % (std.name,std.score)) ... >>> print_score(bart) ZhangSan: 59 |
但是,既然Student实例本身就拥有这些数据,要访问这些数据,就没有必要从外面的函数去访问,可以直接在Student类的内部定义访问数据的函数,这样就把数据给封装起来了。这些封装数据的函数是和Student类关联起来的,我们称之为类的方法
1 2 3 4 5 6 7 8 9 10 | >>> class Student( object ): ... def __init__( self ,name,score): ... self .name = name ... self .score = score ... def print_score( self ): ... print ( '%s:%s' % ( self .name, self .score)) ... >>> bart = Student( 'Zhangsan' , 59 ) >>> bart.print_score() Zhangsan: 59 |
要定义一个方法,除了第一个参数self外,其他和普通函数一样。要调用一个方法,只需要在实例变量上直接调用,出来self不用传递,其他参数正常传递
这样一来,我们从外面看Student类,就只需要知道,创建实例需要给出name和score,而如果打印,都是在Student类的内部定义的,这些数据和逻辑被封装起来了,调用很容易,但却不知道内部的实现细节。
封装的另一个好处是可以给Student内增加新的方法,比如get_grade
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class Student( object ): def __init__( self ,name,score): self .name = name self .score = score def print_score( self ): print ( '%s:%s' % ( self .name, self .score)) def get_grade( self ): if self .score> = 90 : return 'A' elif self .score> = 60 : return 'B' else : return 'C' lisa = Student( 'Lias' , 99 ) bart = Student( 'Zhangsan' , 59 ) print (lisa.name,lisa.get_grade()) print (bart.name,bart.get_grade()) |
运行结果
1 2 | Lias A Zhangsan C |
小结:
类是创建实例的模板,而实例是一个个具体的对象,各个实例拥有的数据都互相独立,互不影响
方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据
通过实例调用方法,就直接操作了对象内部的数据,但无需知道方法内部的实现细节
和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然他们是同一个类的不同实例,但拥有的变量名称可能不同
1 2 3 4 5 6 7 8 9 | >>> bart = Student( 'Zhangsan' , 59 ) >>> lisa = Student( 'lisa' , 99 ) >>> bart.age = 18 >>> bart.age 18 >>> lisa.age Traceback (most recent call last): File "<stdin>" , line 1 , in <module> AttributeError: 'Student' object has no attribute 'age' |
给实例bart绑定了一个age但是lisa没有绑定,所以报错
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!