• 1111111


    在这里插入图片描述

    欢迎关注博主 Mindtechnist 或加入【Linux C/C++/Python社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。



    专栏:《python从入门到实战》


    三大编程范式

    三大编程范式是指:面向过程编程、函数式编程和面向对象编程。三种编程范式只是习惯不同,但是并没有高低之分。正如那句话所说,天下武功门派没有高低之分,只有习武之人的高低之分。
    我们都知道C语言是面向过程的,C++是面向对象的。但是,并不是说C语言一定就只能面向过程,我们用C也可以实现面向对象(实际上在Linux内核中就有很多面向对象的思想),而C++也可以面向过程编程,只能说C++提供了一些特性可以更好地支持面向对象。总之,三大编程范式没有高低之分,也没有和具体的语言绑定这一说。
    需要注意的是,函数式编程 ≠ 用函数编程 ,函数式编程就是用python内的函数来表达出数学层面的函数,二者结合就是函数式编程,即数学函数+python函数
    编程最开始是无组织无结构的,从简单的控制流中按步骤写指令,从指令中提取出重复的代码块或逻辑,组织到一起,便实现了代码复用,这也标志着代码由无结构走向了结构化,写程序的过程也具有了逻辑性。如果我们定义函数,并在函数外定义变量,将变量以参数的形式传递给函数,这就实现了数据与动作的分离,如果更进一步,我们把数据和动作内嵌到一个结构里面,那我们就有了一个对象系统。也就是说,对象是数据和函数的结合物。
    注意:类和对象是有区别的,类是抽象的概念,抽象出共同属性和方法,对象是一个实例,是类实例化出来的对象。面向对象编程并不等于面向类编程,函数和类都可以实现面向对象编程。
    下面是一个用函数实现面向对象的例子

    def city(name, addr, type):
        def init(name, addr, type):
            c = {
                'name':name,
                'addr':addr,
                'type':type,
                'visit':visit,
            }
            return c
    
        def visit(c):
            print('%s %s %s 欢迎您' %(c['addr'], c['type'], c['name']))
    
        return init(name, addr, type)
    
    c1 = city('济南', '山东', '省会')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    类的属性

    声明一个类和声明一个函数很相似,我们使用函数实现面向对象程序设计的时候,是通过返回值得到具体对象的,同样class()也表示执行这个类,也是实例化的过程,和函数一样,它会返回一个对象。
    注意:python2分为经典类和新式类,python3统一都是新式类。

    class c1:
    	‘经典类’
    	pass
    class c2(parent_class):
    	‘新式类’
    	pass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    类的属性有两种,数据属性和函数属性。
    数据属性:变量(实例对象只有数据属性)。
    函数属性:方法,即函数。

    print(classname) #打印类的属性 – 属性名列表
    print(classname.__dict__) #查看类的属性字典 – 属性的键值对
    print(classname.__dict__[‘attrname’]) #获取某一个属性
    classname.__dict__[‘funcname’]() #运行类的某一个属方法
    
    • 1
    • 2
    • 3
    • 4

    python为类内置的特殊属性

    类名.__name__# 类的名字(字符串)
    类名.__doc__# 类的文档字符串
    类名.__base__# 类的第一个父类 – python中所有类都有一个共同父类
    类名.__bases__# 类所有父类构成的元组
    类名.__dict__# 类的字典属性
    类名.__module__# 类定义所在的模块
    类名.__class__# 实例对应的类(仅新式类中)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    类和实例对象

    类的作用域和函数一样,调用类的属性时,会先在自己作用域寻找,自己作用域找不到再去上一层作用域寻找。
    实例只有数据属性,但是实例对象可以调用类的数据属性。
    实际上,实例就是用通过类的__init__产生的,它只包含__init__方法内的一些属性。
    实例没有方法属性,但是实例可以调用类的方法属性,注意调用的方法是类的,而不是实例自己的。
    如果想调用类的方法,需要通过类去调用(实例对象无法调用类的方法,因为不在作用域内),并把实例作为参数传给classname.function(obj)。
    类中的方法,一般都要设置一个参数self,当使用实例调用类的方法时,默认会把实例对象本身传给self。实例调用方法会自动传参self,但是类调用方法需要手动传入实例参数。
    实例是由类中的__init__方法产生的,由__init__传参并返回的对象,实力只含有__init__内的数据属性,但是实例可以访问类的数据属性(__init__外部的),因为实例的作用域也就是__init__的作用域在类的作用域之内,(可以访问上一层作用域的变量),但是实例是没有方法属性的,实例想调用方法只能去找类要,并把自己传过去。(类中的方法都有一个默认参数,在第一个位置,也就是self,它用于指向实例自己)。
    可以对类的数据属性和方法属性进行增删改查;
    对实例的数据属性也可以增删改查,也可以对实例增加方法属性,调用的时候相当于调用实例自己的方法,需要手动把实例自己(不传自己也行,实际上传啥都可以)传进去赋给self(实例调用类的方法时是自动传参给self的,传的是自己)。- 但是不要给实例增加方法,应该把实例的数据属性和方法分离,同一个类创建的实例调用的都是类的方法,这样数据和方法就分离了。

    对象和实例属性

    实际上,实例化就是类名()的过程,其返回结果是一个对象,加上括号的行为和函数的运行非常相似。类和函数一样有作用域,我们可以把类看作是最外层的函数,也就是最大的作用域。实例化会自动触发init函数的运行,最后返回一个值,也就是实例,我们需要的实例属性就存放在init函数的局部作用域里。类有类的属性字典,即类的作用域,而实例有实例的属性字典,即实例的作用域。也就是说,当我们使用对象的方法时obj.func()会先在自己的作用域找,找不到再去外层类的字典中去找,都找不到才会报错。

    类和实例的作用域

    #---------------------------------------------------------
    class People:
    	name = ‘su’
    	def __init__(self, age): #通过自动运行__init__进行实例化
        	self.age = age #实例的作用域在__init__内
    	def test(self, string)
        	print(‘test %s’ %string)
    
    p1 = People(18)
    p1.name = ‘yy’ 
    #相当于在实例的字典中增加一个属性,和类的字典毫无关系
    print(People.name) # su
    print(p1.name) #yy
    
    #---------------------------------------------------------
    
    name = ‘su’
    class People:
    	def __init__(self, age): 
        	self.age = age 
    	def test(self, string)
        	print(‘test %s’ %string)
    p1 = People(18)
    print(p1.name) #err – 只会在类的作用域内部找
    
    #---------------------------------------------------------
    
    class People:
    	def __init__(self): #__init__除了不能返回值,和普通函数无区别
        	age = input(input age’) 
        	self.age = age 
    	def test(self, string)
        	print(‘test %s’ %string)
    #千万不要这样做
    
    #---------------------------------------------------------
    
    name = ‘su’
    class People:
    	def __init__(self, age): 
        	self.age = age 
        	print(‘name: --, name) #可以打印出
    	def test(self, string)
        	print(‘test %s’ %string)
    p1 = People(18)
    #只有以点.去访问的时候,才遵循在类的内部去找的原则,因为.是成员运算符
    
    #---------------------------------------------------------
    
    name = ‘su’
    class People:
        name = ‘tt’
    	def __init__(self, age): 
        	self.age = age 
        	print(‘name: --, name) #su
    	def test(self, string)
        	print(‘test %s’ %string)
    p1 = People(18)
    print(People.name)
    print(p1.name)
    # .调用方式在类内部寻找,遵循类的作用域,在类和实例的字典中去找
    #不用.访问,那么就和类还有实例没关系,就是访问普通变量,它就不会在类还有实例的字典内找变量,而是查找普通变量
    
    #---------------------------------------------------------
    
    class People:
    	name = ‘tt’
    	l = [‘a’, ‘b’]
    	def __init__(self, age): 
        	self.age = age 
    	def test(self, string)
        	print(‘test %s’ %string)
    p1 = People(18)
    print(p1, l)
    p1.l = [1, 2, 3] #改的是实例,在实例的字典中加了一个列表
    #给实例新增加了一个新属性,= 表示新增
    print(People.l)
    print(p1.l)
    p1.l.append(‘c’) #这里没有用等号,所以不会给实例p1增加新属性
    #这就是改的类的属性了
    print(p1.__dict__) #实例的属性字典
    print(People__dict__) #类的属性字典
    
    
    • 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
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    静态与组合

    静态属性

    @property - 装饰器

    class People:
    	def __init__(self, name, age): 
        	self.name = name 
    	self.age = age
    	@property 
    	def get_attr(self):
        	#print(‘%s - %s’ %( self.name, self.age))
        	return [name, age]
    p1 = People(‘su’, 17)
    p1.get_attr  #调用的时候不再加()就可以执行
    #调用方法属性和调用数据属性一样,这样就隐藏了背后的实现逻辑
    #调用者调用的时候,只能看到结果,但是无法得知背后的逻辑实现
    #把方法属性封装起来像数据属性一样
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    类方法

    @classmethod

    class People:
        tag = 1
    	def __init__(self, name, age): 
        	self.name = name 
    		self.age = age
    	@property 
    	def get_attr(self):
        	#print(‘%s - %s’ %(self.name, self.age))
        	return [name, age]
    	def get_tag(self):
        	print(%s’ %self.tag)
    People.get_tag(x) #原则上可以传入任何参数,但是底层self.tag限制了必须传入一个实例
    p1 = People(‘su’, 17)
    People.get_tag(p1)
    #我的需求是,只打印类的方法,我不想和实例捆绑在一块
    class People:
        tag = 1
    	def __init__(self, name, age): 
        	self.name = name 
    		self.age = age
    	@property 
    	def get_attr(self):
        	#print(‘%s - %s’ %(self.name, self.age))
        	return [name, age]
    	@classmethod
    	def get_tag(cls): #参数是一个类名
        	print(%s’ %cls.tag)
    People.get_tag() #将类和实例分离 – 提供了由类调用的方法 – 类方法
    #类方法也会自动传参,会把调用的类名自动传入给cls
    #类方法只能调用类属性,不能调用实例属性,实例属性是由self调用的
    #只要参数带self,那么这个方法就和实例绑定了
    #cls就是和类绑定
    #实例也能调用类方法 – 但是最好不要这样做,类方法出现的意义就是给类调用
    
    • 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
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    静态方法

    @staticmethod

    class People:
    	def __init__(self, name, age): 
        	self.name = name 
    		self.age = age
    	@property 
    	def get_attr(self):
        	print(%s - %s’ %(self.name, self.age))
    	@staticmethod #类的工具包
    	def do_thing(a, b, c):
        	print(a, b, c)
    	def do_thing2(a, b, c):
        	print(a, b, c)
    
    print(People.__dict__)
    p1 = People(‘su’, 17)
    print(p1.__dict__)
    People.do_thing(1, 2, 3) #ok – 不会自动传参
    p1.do_thing(1, 2, 3) #ok – 不会自动传参
    People.do_thing2(1, 2, 3) #ok
    p1.do_thing2(1, 2, 3) #error #p1会自动把自己传进去 – 参数错误
    
    #  @property – 将方法和实例绑定 – 用self调用实例属性 – 自动传入实例本身给self
    #  @classmethod – 将方法和类绑定(和实例就没关系了)- 用cls调用类的属性 – 自动传入本身给cls
    #  @staticmethod – 既不和实例绑定也不和类绑定,和实例和类都没关系了,是一个类的工具包 – 不会自动传参
    # 静态方法staticmethod只是名义上归属类管理,不能使用类变量和实例变量,是类的工具包 – 既没有self也没有cls,无法通过.去调用属性
    
    • 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

    组合

    组合是做关联的,类与类之间没有共同点,但是它们之间是有关联的,这时就用组合去解决,去建立关联。(实例对象做参数,类做参数)
    在这里插入图片描述
    这里面的Head()、Foot()等就是一个对象,类名加()本身就是实例化的意思,所以上面的效果和直接传递一个实例对象的参数效果是一致的。


    在这里插入图片描述
    在这里插入图片描述


  • 相关阅读:
    26. 删除有序数组中的重复项
    Ajax——AJAX实现省市联动
    超全汇总 | 基于Camera的3D目标检测算法综述!(单目/双目/伪激光雷达)
    3d模型里地毯的材质怎么赋予?---模大狮模型网
    前端base64转文件输出
    Unity笔记--渲染顺序
    HarmonyOS开发(一):开发工具起步
    永磁同步电机转子位置估算专题——正交锁相环
    常用的BI工具有哪些?口碑怎样?
    新相微在科创板过会:计划募资约15亿元,2022年业绩开始下滑
  • 原文地址:https://blog.csdn.net/qq_43471489/article/details/137366883