首页 > 编程语言 >Python面向对象之绑定方法和非绑定方法

Python面向对象之绑定方法和非绑定方法

时间:2024-01-11 16:55:25浏览次数:30  
标签:name Person Python self 绑定 面向对象 print 方法

绑定方法与非绑定方法

【一】概要

  • 在 Python 中,绑定方法是指将类的实例与类的方法关联起来的过程。绑定方法包含类实例作为第一个参数,通常被称为 self。当通过实例调用类的方法时,Python 会自动传递实例作为第一个参数,这个过程就是方法绑定。

【二】常用方法

【1】绑定方法(动态方法)

  • 普通方法(即不使用任何装饰器的方法)以及使用 @classmethod 装饰器修饰的类方法都是绑定方法。它们都将实例作为第一个参数传递,并与实例绑定

    • 绑定给对象的方法
    class Person(object):
        name = 'user'
        
    	'''正常定义在类中的函数,就被称为绑定给对象的方法'''
        def func(self, meter):
            print(f"{self.name} 正在跑步 {meter} m ")
    
    • 绑定给类的方法@classmethod
    class Person(object):
        name = 'user'
    	
        '''通过装饰器classmethod装饰的方法,就称为类绑定方法'''
        @classmethod
        def func_class(cls):
            print("正在使用类绑定方法")
    

【2】非绑定方法(静态方法)@staticmethod

class Person(object):
    name = 'user'
	
    '''通过装饰器staticmethod装饰的方法,就称为非绑定方法'''
    @staticmethod
    def func(name, meter):
        '''静态方法就是一个在类中的普通函数'''
        print(f"{name} 跑了 {meter} 米")

【3】总结

class Person(object):
    data_attribute = '数据属性'

    def func(self):
        print("这是普通的方法,也可以称为绑定给对象的方法")

    @classmethod
    def func1(cls):
        print("这是绑定给类的方法")

    @staticmethod
    def func2():
        print('这是一个普通的函数')


print(Person.__dict__)
# {'__module__': '__main__',
# 'data_attribute': '数据属性',
# 'func': <function Person.func at 0x000002551C6627A0>,
# 'func1': <classmethod(<function Person.func1 at 0x000002551C6635B0>)>,
# 'func2': <staticmethod(<function Person.func2 at 0x000002551C941A20>)>,
# ……

【三】详解

【1】绑定方法(动态方法)

  • 普通方法(即不使用任何装饰器的方法)以及使用 @classmethod 装饰器修饰的类方法都是绑定方法。它们都将实例作为第一个参数传递,并与实例绑定

    • 绑定给对象的方法
    class Person(object):
        name = 'user'
    
        def func(self, meter):
            print(self)
            print(f"{self.name} 正在跑步 {meter} m ")
    
    
    '''绑定方法依赖与实例后的对象,只有当有实例的对象时才能使用'''
    # 当对象直接调用绑定方法
    p = Person()   # <__main__.Person object at 0x00000211BDEAB910>
    p.func(meter=100)   # # user 正在跑步 100 m
    
    
    # 当使用类调用绑定方法时
    # 会发现,需要我们传递第一个参数了,如果不传将会报错
    
    # Person.func(meter=100)
    # TypeError: Person.func() missing 1 required positional argument: 'self'
    Person.func(self=Person(), meter=200)
    # print(self)|输出>>>:<__main__.Person object at 0x00000297A2659720>
    # print(f"{self.name} 正在跑步 {meter} m ")|输出>>>:user 正在跑步 200 m
    
    
    '''我们可以注意到 当类调用绑定方法时,self我们如果传的不是对象,也并不会报错'''
    Person.func(self=Person, meter=200)  # Person不加小括号的含义也就是类
    # <class '__main__.Person'>   # 可以看到self的值已经变成了类,而不是对象了
    # user 正在跑步 200 m    # 输出是正常的
    
    '''这是因为在python中一切皆对象,所有类型都可以作为对象传值'''
    
    '''但是,需要注意,当你的方法中有需要调用对象中的属性或者类中的属性时,会因为找不到对应的值报错'''
    
    Person.func(self='字符串作为对象', meter=300)
    
    # AttributeError: 'str' object has no attribute 'name'
    
    '''所以,一般情况下,使用类调用绑定给对象的方法时,传递的对象值为类名加小括号【Person()】'''
    
    • 绑定给类的方法@classmethod
    class Person(object):
        name = 'user'
    
        def func(self, meter):
            print(self)
            print(f"{self.name} 正在跑步 {meter} m ")
    
        @classmethod
        def func_class(cls):
            print(cls)
            '''__name__ 的含义是获取到类名'''
            print(f"类 {cls.__name__} 正在使用类绑定方法")
    
    
    '''通过装饰器classmethod装饰的方法,就称为类绑定方法'''
    # 对于类绑定方法,self参数,也就变成了cls,代表着代替的是类
    # 类就可以直接调用
    Person.func_class()
    # <class '__main__.Person'>
    # Person 正在使用类绑定方法
    
    '''绑定给类的方法,对象也是可以正常使用'''
    p = Person()
    p.func_class()
    # <class '__main__.Person'>   # 因为该对象是通过类实例化得到的,程序会自动将所属的类作为参数传递给方法
    # Person 正在使用类绑定方法
    
    class Person(object):
        name = 'user'
    
        def func(self, meter):
            print(self)
            print(f"{self.name} 正在跑步 {meter} m ")
    
        @classmethod
        def func_class(cls):
            print(cls)
            '''__name__ 的含义是获取到类名'''
            print(f"类 {cls.__name__} 正在使用类绑定方法")
    
    '''类名后小括号中,可以放其他类,含义是继承,具体请看下一篇文章面向对象的三大特性'''
    class People(Person):
        # 继承就是继承父类的属性,包括函数属性(方法)和数据属性
        ...
    
    
    p = People()
    p.func_class()
    '''此处是为了展示__name__的用法'''
    # <class '__main__.People'>
    # 类 People 正在使用类绑定方法
    
    

【2】非绑定方法(静态方法)@staticmethod

class Person(object):
    name = 'user'

    @staticmethod
    def func(name, meter):
        '''静态方法就是一个在类中的普通函数'''
        print(f"{name} 跑了 {meter} 米")


'''静态方法的第一个参数并不会被当成self参数,而可以忽略'''
'''并且,对象可以直接调用,类也可以直接调用'''
p = Person()
p.func(name="user001", meter=100)
# user001 跑了 100 米
Person.func(name="user002", meter=500)
# user002 跑了 500 米
'''而万事万物都是有代价的,静态函数就无法直接通过self参数灵活的调用和传递参数'''

class Person(object):
    name = 'user'
    def __init__(self,age):
        self.age = age

    @staticmethod
    def func():
        '''如果需要调用类中的其他属性,就需要通过类名+属性名调用'''
        class_data = Person.name
        print(f"类中的数据属性{class_data},就不能直接灵活调用了")
        
        '''为什么不能灵活调用了?因为这样写就已经写死了,这样写就只能够调用类中属性,而不能够调用对象独有的属性了'''

        
    def normal_func(self):
        '''以绑定给对象方法举例'''
        print(f"可以调用类的属性{self.name}")
        print(f"也可以调用自己独有的属性{self.age}岁")



p = Person(age=18)
p.func()
p.normal_func()
# 输出:
# 类中的数据属性user,就不能直接灵活调用了
# 可以调用类的属性user
# 也可以调用自己独有的属性18岁

【3】Python中,一切皆对象

  • 当我们打开源码,不难发现,Python中的基本数据类型都是通过类定义的
  • 通过type函数也可以发现,<class 'list'>

image-20240110200151058

  • 类中定义的方法也就是我们可以通过【.】来调用的方法
  • 也有一些魔法方法,如__init__

image-20240110201541231

  • 当我们选择list() 强转数据类型的时候,其实python就是帮我们执行了实例化了一个list类下的对象,调用了__init__方法初始化。
  • 虽然底层代码由于是CPython导致我们无法看到底层代码,但也可知,python中的一切数据类型,其实都是类初始化出来的对象

“前路漫漫其修远兮,吾将上下而求索。”

当越来越往深处接触,越是发觉前人的智慧是多么强大,同样的方法又衍生出了这么多妙用!

【4】总结

class Person(object):
    name = 'user'

    def read(self):
        print(f"{self.name} 正在读书")

    @classmethod
    def write(cls):
        print(f"{cls.run()} 正在写作业")
        print("如果此处不传实例化的对象,那么如果需要调用某些在类中的数据属性,将会报错")

    @staticmethod
    def run():
        print(f"跑步,无法调用类中的数据属性和函数属性")

p = Person()
p.read()
p.write()
p.run()

Person.write()
Person.read(p)
# Person.read('str')
# AttributeError: 'str' object has no attribute 'name'
Person.run()

动态方法(实例方法)、类方法、静态方法的使用场景

  1. 动态方法(实例方法):

    • 绑定对象: 这些方法是绑定给对象的,即在调用时,会将调用它们的对象作为第一个参数传递给方法。这使得方法能够访问和操作对象的属性。

    • 使用场景: 当方法需要访问或修改实例的属性时,通常使用动态方法。这些方法可以访问对象的状态,并对其进行操作。

  2. 类方法:

    • 绑定到类: 类方法是绑定到类而不是实例的方法。它们接受类作为第一个参数,通常命名为 cls
    • 使用场景: 类方法通常用于对类级别的属性进行操作或在创建对象之前执行某些逻辑。当方法需要与整个类相关,而不是特定实例时,可以使用类方法。
  3. 静态方法:

    • 不绑定对象: 静态方法是类的一部分,但它们不绑定到实例。它们不能访问实例的属性,因为它们不接受 self 参数。它们只能访问类的属性,因为它们被绑定到类本身。
    • 使用场景: 当一个方法与类有关,但不需要访问或修改实例状态时,可以使用静态方法。静态方法在方法中不需要访问 self,因此可以用于执行与类相关的任务。

【5】实际案例

【5.1】类绑定方法:自动生成固定初始化信息的对象

'''自动生成对象'''


class MySql():
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

    @classmethod
    def make_obj(cls):
        return cls(ip='127.0.0.1', port=3306)


mysql_obj = MySql.make_obj()

【5.2】静态方法:生成工具类供外界调用

class Tools():
    '''当我们定义一个工具类,希望外界调用时,就可以使用静态方法'''

    @staticmethod
    # 生成随机ID
    def creat_id():
        '''函数内部并不依赖对象的属性或类的属性'''
        import uuid
        return uuid.uuid4()

    @staticmethod
    # 加密
    def encrypt_data(data):
        from hashlib import md5
        md5 = md5()
        md5.update(data.encode('utf8'))
        return md5.hexdigest()


random_id = Tools.creat_id()
print(random_id)   # b45cb0a0-7baa-4f7c-b84b-1437bf628070

encrypted_data = Tools.encrypt_data('hello')
print(encrypted_data)  # 5d41402abc4b2a76b9719d911017c592

标签:name,Person,Python,self,绑定,面向对象,print,方法
From: https://www.cnblogs.com/Lea4ning/p/17958914

相关文章

  • 【Python基础】函数进阶(匿名函数、装饰器、闭包等)
    简介函数进阶的使用,包括匿名函数、装饰器、闭包等匿名函数指函数是没有函数名称的,临时使用的微函数。使用lambda表达式来声明,语法格式如下:lambda[arg1[arg2,...,argn]]:表达式*[arg1,arg2,...,argn]为函数的参数列表,可有可无。*表达式:表示函数体,必须......
  • python代码规范pep8
    python代码规范pep8  1.pep8介绍2.pep8安装配置3.pep8安装问题 1、pep8介绍pep8是python编码规范 2、pep8安装配置121.pycharm安装PEP8:pipinstallautopep82.File->settings->Tools->ExternalTools ->点击+配置.png123453.Name......
  • python基础之list、tuple、dict、set
    python基础,list,tuple,dict,set比较1.list:list是一种有序的集合,可以随时添加和删除其中的元素。用len()函数可以获得list元素的个数.list是一个可变的有序表>>>classmates=['Michael','Bob','Tracy']>>>len(classmates)3>>>classmates[0]//用......
  • 利用Python和fake_useragent模拟不同浏览器访问
    在Python中,您可以使用requests库来发送HTTP请求,并使用UserAgent对象设置请求头中的User-Agent字段,以模拟不同浏览器或设备。以下是一个示例代码,演示如何使用requests库和fake_useragent库获取https://www.mafengwo.cn/网页的内容:首先,确保您已经安装了requests和fake_useragent库,您......
  • Python Flask 返回函数 、带值的函数
    前言全局说明一、安装flask模块官方源:pip3installflask==2.3.2国内源:pip3installflask==2.3.2-ihttp://pypi.douban.com/simple/--trusted-hostpypi.douban.com以上二选一,哪个安装快用哪个flask安装时间2023-11更多国内源:https://www.cnblogs.com/wutou......
  • WPF的DataGrid绑定DataTable调研小记
    公司有个项目,界面很卡,同事怀疑是DataTable刷新引起的,我写了一个小Demo测试一下这块的性能。测试的结果DataTalbe的绑定非常的耗时我的前台代码:<DataGridGrid.Row="1"AutoGenerateColumns="True"BorderBrush="LightGray"ItemsSource="{BindingItems}"......
  • Python实现软件设计模式8:桥接模式 Bridge Pattern
    动机将抽象部分与实现部分分离,使他们都可以独立地变化。用抽象关联取代传统的多层继承。将类之间的静态继承关系转换为动态的对象组合关系。上图展示的软件系统中存在两个独立地变化维度,分别是抽象类(Abstraction)和实现类(Implementor),它俩都是接口、都分别可以独立地扩展出多......
  • Python Flask html 模板的继承
    前言全局说明一、安装flask模块官方源:pip3installflask==2.3.2国内源:pip3installflask==2.3.2-ihttp://pypi.douban.com/simple/--trusted-hostpypi.douban.com以上二选一,哪个安装快用哪个flask安装时间2023-11更多国内源:https://www.cnblogs.com/wutou......
  • Python实现软件设计模式7:适配器模式 Adapter Pattern
    动机有两个不存在直接继承或关联关系的类A、B,A希望能利用到B类中某个已存在的、功能完善的方法,而不再去具体实现A的接口源码;适配器模式使接口不兼容的那些类可以一起工作。主要角色目标类Target抽象接口类适配者Adaptee适配器Adapter具体实现接口客户端C......
  • python第三节:Str字符串类型(3)
    str.index(sub[, start[, end]])类似于 find(),但在找不到子字符串时会引发 ValueError。例子:str1='mynameisjack!'print(str1.index('i'))print(str1.index('b'))结果:Traceback(mostrecentcalllast): File"D:/pythonProject/test/test2024011......