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的区别

  1. 当单独打印对象时,会调用str方法
  2. 如果调用内置数据类型时(列表,元组等),将会优先调用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())

  

posted @   新兵蛋Z  阅读(245)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示