Python——面向对象
什么是类class:
具有相同方法和属性的一类事物叫做类。
什么是对象,实例:
一个拥有具体属性值和动作的具体个体。
什么是实例化:
从一个类得到一个具体对象的过程。
1 2 3 4 5 6 7 8 9 10 | class Foo( object ): def __init__( self ): print ( 11111 ) print ( self ) name = 'haha' lis = [] def func( self ): pass onj1 = Foo() #实例化一个Foo对象。 print (onj1) |
实例化一个对象的时候,会发生:
1. 在内存中开辟一个对象空间。
2. 自动执行类中的__init__方法,并将这个对象空间(内存地址)传给了__init__方法的第一个未知参数self。
3. 在__init__方法中通过self给对象空间添加属性。
什么是组合:
一个类的对象作为另一个类对象的实例变量。
面向对象特点:
1. class 后首写字母必须大写
2. self为实例化对象的内存指向,每个方法默认必须有。必须要注意每一个self的内存对象指的是哪一个,还有就是在哪个方法内使用的。
基础格式:
1 2 3 4 5 6 7 8 9 | class Foo( object ): #class + 类名称(首字母大写)(object为生成内存地址使用,py3不写也可以,py2必须写) def __init__( self ,name,age,): #初始化,在执行序列化时,就需要执行初始化过程。 self .name = name #将对象和导入的参数进行对应。 self .age = age def func( self ): print ( self .name, self .age) #调用类的变量。 obj1 = Foo( 'xuan' , 22 ) #序列化一个类,并赋值给obj1这个变量中。 obj1.func() #运行obj1内的方法。 |
三大特点:
封装
1. 将多个相同类型的方法封装到一个类中,使其统一,
2. 将常用变量保存在类中,以供方法调用。
1 2 3 4 5 6 7 | class Foo( object ): name = 'xuan' #将常用变量存在类中,方便方法调用 def func( self ): print ( self .name) obj1 = Foo() print (obj1.name) < / span>< / span>< / span>< / span>< / span> |
成员修饰符
1. 未加下划线变量或方法
2. 加_单下划线的变量或方法
3. 加__双下划线的变量或方法
未加下划线的变量或方法。
全局可用,可在任意位置调取使用或更改。模块导入调用也可以。
1 2 3 4 5 6 7 8 | class Foo( object ): name = 'xuan' #公有 def func( self ): print ( self .name) obj1 = Foo() print (obj1.name) #在类外可以正常调用 obj1.func() |
加_单下划线的变量或方法。
单个下划线是一个Python命名约定,表示这个名称是供内部使用的。 它通常不由Python解释器强制执行,仅仅作为一种对程序员的提示。
以单个下划线开头的变量或方法仅供内部使用。 该约定在PEP 8中有定义。
1 2 | from test import * obj1 = _Foo( 'yong' ) #在导入一个模块并使用类时,由于带有下划线,导入*的话是会报错的。 |
加__双下划线的变量或方法
只能在类的内部使用,既不能在类的外部调用,也不能在子类中使用。
1 2 3 4 5 6 7 8 9 10 | class Obj1(): def __init__( self ): self .__name = 'xuan' print ( self .__name) def pr( self ): print ( self .__name) foo = Obj1() foo.pr() # print(foo.__name) #报错。 |
可以使用_Foo__name 强制访问
1 2 3 4 5 6 7 8 9 | class Foo( object ): __name = 'xuan' #公有 def func( self ): print ( self .__name) obj1 = Foo() print (obj1.name) #会报错 print (obj1._Foo__name) #可强制在外部访问 obj1.func() #只能调用内部方法,用内部方法调用 |
1 2 3 4 5 6 7 8 9 | class Obj1(): def __init__( self ): # __name = 'xuan' #这样是不行的。 self .__name = 'xuan' def pr( self ): print ( self .__name) obj1 = Obj1() obj1.pr() |
继承
将一个或多个类关联到一起,当此类中没有对应的方法时,会查找父类(继承类),多个继承类则从左至右依次查找。
注意:
1. 当多继承时,一定要注意self的指向和初始方法调用点在哪里。
2. 多个类中如果有多个相同方法,可以放到基类中避免重复编写(相当于装饰器)。
3. 如果自己和父类都想调用相同属性,方法。使用super&指定类名。
1 2 3 4 5 6 7 8 9 10 | class Foo( object ): #父类(基类) name = 'xuan' def func( self ): print ( self .name) class Content(Foo): #子类(派生类) def func1( self ): print ( self .name) obj1 = Content() print (obj1.name)< / span>< / span>< / span>< / span>< / span> |
新式类与经典类:
Py2继承object就是新式类,默认是经典类。Py3都是新式类,默认继承object
新式类:
1. 继承object
2. 支持super
3. 多集成,广度优先(C3算法)
4. 支持mro方法
经典类:
1. 不继承object
2. 不支持super
3. 多继承,深度优先
4. 没有mro方法
继承的查找顺序:
广度优先:
Py3所有类默认。
深度优先:
1. Py2默认
2. 不查找相同的基类
mro方法:
获取类继承顺序。
1 2 | import inspect print (inspect.getmro(A)) |
多态(鸭子模型)
一个类表现出来的多种形态
鸭子模型:
多种形态用一个类表现出来。
1 2 3 4 5 6 7 | class Foo( object ): def func( self ,name): #name可以是任何形态的数据类型。(任何物种) print (name[ 2 ]) #而多种形态下,必须要有可切片功能的才能正常执行。(鸭子叫) obj1 = Foo() obj1.func( 'haha' ) < / span>< / span>< / span>< / span>< / span> |
类变量与实例变量:
1. 类变量小于实例变量
1 2 3 4 5 6 7 8 9 | class Foo( object ): name = 'xuan' #类变量 def func( self ): print ( self .name) obj1 = Foo() obj1.name = 'yong' #实例变量 print (Foo.name) #只输出类变量 obj1.func() |
2. 在类内部的类变量在解释的时候就会执行,而内部的方法时在调用的时候再执行。
1 2 3 4 | class Foo( object ): print ( 111 ) #在python解释器解释时,就会直接运行类中的类变量。 def func( self ): pass |
1 2 3 4 5 6 | class Foo( object ): print ( 111 ) #在python解释器解释时,就会直接运行类中的类变量。 def func( self ): pass class Bor( object ): print ( 222 ) #类在嵌套时也同样会运行类变量。 |
属性
@property
1 2 3 4 5 6 7 8 9 | class Foo( object ): name = 'xuan' def __init__( self ,name): self .name = name @property def func( self ): print ( self .name) obj1 = Foo( 'yong' ) obj1.func #无需使用()来执行,并且要求必须没有传参的情况下。 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class Foo(): @property def AAA( self ): print ( '111' ) @AAA .setter def AAA( self ,value): print ( '222' ) @AAA .deleter def AAA( self ): print ( '333' ) f1 = Foo() f1.AAA = 'aaa' f1.AAA del f1.AAA ''' 222 111 333 只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter ''' |
方法
方法和函数的区别:
1. 通过打印函数名确定
1 2 3 4 5 6 7 8 9 10 11 | def func(): pass print (func) # class A(): def func( self ): pass obj = A() print (obj.func) #bound method A.func of <__main__.A object at 0x00000256AD077700> |
2. 通过types模块验证。
1 2 3 4 5 6 7 8 9 10 11 12 13 | from types import FunctionType from types import MethodType def func(): pass class A: def func( self ): pass obj = A() print ( isinstance (func,FunctionType)) #True print ( isinstance (A.func,FunctionType)) #True print ( isinstance (obj.func,FunctionType)) #False print ( isinstance (obj.func,MethodType)) #True |
3. 函数的是显示传递数据,如我们需要指明为len()函数传递一些要处理的数据。
4. 方法中的数据则是隐式传递的。
5. 函数跟对象无关
6. 方法可以操作类内部的数据
7. 方法跟对象是关联的,strip()是通过str对象来调用的。
实例方法:
定义:第一个参数必须是实例对象,该参数名一般约定为“self”,通过它来传递实例的属性和方法(也可以传类的属性和方法)
调用:只能由实例对象调用
详解:实例方法就是类的实例能够使用的方法。、
静态方法
定义:使用装饰器@staticmethod。参数随意,没有“self”和“cls”参数,但是方法体中不能使用类或实例的任何属性和方法。
调用:实例对象和类对象都可以调用、
详解:静态方法是类中的函数,不需要实例。静态方法主要是用来存放逻辑性的代码,逻辑上属于类,但是和类本身没有关系,也就是说在静态方法中,不会涉及到类中的属性和方法的操作。可以理解为,静态方法是一个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护。
@staticmethod
1 2 3 4 5 6 | class Foo( object ): @staticmethod def func(): print ( 111 ) Foo.func() |
类方法
定义:使用装饰器@classmethod,第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法。(不能传实例的属性和方法)
调用:实例对象和类对象都可以使用
详解:原则上,类方法是将类本身作为对象进行操作的方法。
classmethod
1 2 3 4 5 6 7 8 9 | class Foo( object ): name = 'xuan' def __init__( self , name): self .name = name @classmethod def func( cls ): # cls为类的实例化,不是变量的实例化 print ( cls .name) # cls.name 为类变量 obj1 = Foo( 'yong' ) obj1.func() |
super
1 2 3 4 5 6 7 8 9 10 11 12 | class Foo( object ): def func( self ): print ( 111 ) class Base(Foo): def func1( self ): super ().func() #在运行方法时,可以同时运行Foo类中的func方法。 pass obj1 = Base() #如果是多继承,那么就会按照查找顺序进行查找。 obj1.func1() |
类中特殊方法:
__new__&__init__&__call__
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | class Foo( object ): def __init__( self ,a1): ''' 称为:初始化方法 初始化使用,先有用new方法创建一个对象后,再使用init进行对象的初始化。 ''' self .a1 = a1 print ( 1 ) def __new__( cls , * args, * * kwargs): ''' 称为:构造方法 new为创建一个空对象。在实例化时,就会首先进行此方法来创建一个空对象。 :return: 返回什么,obj1就等于什么。 ''' print ( 2 ) return object .__new__( cls ) def __call__( self , * args, * * kwargs): ''' 当没有call方法时,对象加()会报错,而类中有call时,那么就会运行call方法中的内容。 :param args: :param kwargs: :return: ''' print ( 3 ) obj1 = Foo( '1111' ) obj1() |
iter
class Foo(object):
def __iter__(self,a1):
'''
称为:在将Foo实例化后,进行for循环时,将会执行此操作
'''
yield 1
foo = Foo()
for i in foo:
print(i)
getitem/setitem/delitem
1 2 3 4 5 6 7 8 9 10 11 12 13 | class Foo( object ): def __setitem__( self , key, value): print (key) print (value) def __getitem__( self , item): print (item) def __delitem__( self , key): print (key) obj1 = Foo() #和字典一样的形式。 obj1[ 1 ] = 2 #当有这样形式的对象设置时,会调用内部的setitem方法。 obj1[ 3 ] #调用内部getitem del obj1[ 1 ] #调用内部delitem |
str
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Foo( object ): def __init__( self , name, age): self .name = name self .age = age def __str__( self ): ''' 有str方法时,将会把对象以字符串形式输出。return什么,就输出什么。但如果运行方法,那么就不会有影响。 :return: ''' return f "{self.name}:{self.age}" user_list = [Foo( 'xuan' , 12 ), Foo( 'yong' , 23 ), Foo( 'jun' , 34 )] for i in user_list: print (i) |
str和repr的区别
- 当单独打印对象时,会调用str方法
- 如果调用内置数据类型时(列表,元组等),将会优先调用repr方法。
class Name():
def __init__(self,username):
self.username=username
def __str__(self):
return self.username
def __repr__(self):
return self.username
class Class():
def __init__(self,name):
self.name = name
self.name_list = []
n1 = Name('he1')
n2 = Name('he2')
c1 = Class('C1')
c1.name_list.append(n1)
c1.name_list.append(n2)
for i in c1.name_list:
print(i)
print(c1.name_list)
dict
只能进行查询,不能增删改。
1 2 3 4 5 6 7 8 9 | class Foo( object ): def __init__( self , name, age): self .name = name self .age = age obj1 = Foo( 'xuan' , 123 ) print (obj1.__dict__) #将形参和实参进行一一对应,组成字典。 #{'name': 'xuan', 'age': 123} |
enter&exit
1 2 3 4 5 6 7 8 9 10 11 12 | class Foo( object ): ''' 先进行enter方法中的代码,然后返回给ff,最后缩进完成时裕兴exit方法。 ''' def __enter__( self ): self .x = 8 + 8 return self .x def __exit__( self , exc_type, exc_val, exc_tb): print ( 'exit' ) with Foo() as ff: print (ff) print (ff) |
对象的加减乘除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Foo1( object ): def __add__( self , other): print ( 112 ) class Foo( object ): ''' self为obj1 ,other为obj2,返回什么val就是什么。 ''' def __add__( self , other): return 123 obj1 = Foo() obj2 = Foo1() val = obj1 + obj2 print (val) |
类判断:
type
1 2 3 4 5 6 7 8 9 | class Foo( object ): pass class Base(Foo): pass obj1 = Base() if type (obj1) = = Base: #判断对象和和类是否一致。 print ( 1 ) |
issubclass
1 2 3 4 5 6 7 8 9 10 | class Foo( object ): pass class Base(Foo): pass class Bass(): pass obj1 = Base() print ( issubclass (Base,Foo)) #True print ( issubclass (Bass,Foo)) #False |
isinstance
1 2 3 4 5 6 7 8 9 10 | class Foo( object ): pass class Base(Foo): pass class Bass(): pass obj1 = Base() print ( isinstance (obj1,Foo)) #判断对象是否是类或基类的实例 print ( isinstance (obj1,Bass)) #False |
数据结构:
这里的队列和栈会在网络编程时用到。
队列:
像排队取号吃饭一样,先拿到号的肯定会先进去吃饭。
先进先出:FIFO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #队列: 先进先出 class Queue( object ): def __init__( self ): self .data_list = [] def push( self ,name): self .data_list.insert( 0 ,name) def pop( self ): return self .data_list.pop() obj1 = Foo() obj1.push( '1' ) obj1.push( '2' ) obj1.push( '3' ) print (obj1.pop()) print (obj1.pop()) print (obj1.pop()) |
栈:
像弹夹里装子弹一样,最后进去的反而会最先被打出来。
后进先出,LIFO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #栈: 后进先出 class Stack( object ): def __init__( self ): self .data_list = [] def push( self ,name): self .data_list.append(name) def pop( self ): return self .data_list.pop() obj1 = Foo() obj1.push( '1' ) obj1.push( '2' ) obj1.push( '3' ) print (obj1.pop()) print (obj1.pop()) print (obj1.pop()) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)