• 面向对象——细节


    类的细节

    1.property


    方法在类中就是一种行为,行为是一个动词,可有的时候,我们想让方法这个'动词'变成'名词',

    提供这样的机制。来达到实际所需的效果。property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值。

    例子一: 特性的使用

    class People:
        def __init__(self, name, weight, height):
            self.name = name
            self.weight = weight
            self.height = height
    
        @property # 通过这个装饰器,我们让方法立即变身
        def bim(self):
            return self.weight / (self.height ** 2)
    
    
    p = People('yk', 55, 1.65)
    print(p.bim) # 20.202020202020204
    # 咦,不是应该是 p.bim()嘛。别忘了,我们在方法的前面加了'@property'。成功包装成一个名词'属性',有时候你确实需要这种效果。

    注意:

    此时的特性bim不能被赋值

    p.bim=23 # 为特性bim赋值
    # AttributeError: can't set attribute

    为什么要用property

    将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则。

    例子二:我们真的不能通过property设置值吗?

    class Foo:
        def __init__(self,val):
            self.__NAME=val #将所有的数据属性都隐藏起来
    
        @property
        def name(self):
            return self.__NAME #obj.name访问的是self.__NAME(这也是真实值的存放位置)
    
        @name.setter # 可以用这个装饰器修改
        def name(self,value):
            if not isinstance(value,str):  #在设定值之前进行类型检查
                raise TypeError('%s must be str' %value)
            self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME
    
        @name.deleter # 删除时会触发
        def name(self):
            raise TypeError('Can not delete')
    
    f=Foo('yk')
    print(f.name) # yk
    # f.name=10 #抛出异常'TypeError: 10 must be str'
    f.name = '小明'
    print(f.name) # 小明,修改成功
    del f.name #抛出异常'TypeError: Can not delete'

    2.绑定方法和非绑定方法

    一、绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入):

    1.绑定到对象的方法:没有被任何装饰器装饰的方法。

    对象.boud_method(), 自动将对象当作第一个参数传入
    (属于类的函数,类可以调用,但是必须按照函数的规则来,不会自动传值)

    2.绑定到类的方法,用 @classmethod 装饰器修饰的方法

    类名.boud_method(), 自动将类当作第一个参数传入
    (其实对象也可调用,但仍将类当作第一个参数传入)

    class Foo:
        def __init__(self, name):
            self.name = name
    
        def myself(self):
            print("我是 %s" % self.name)
    
        @classmethod # 类方法
        def clss(cls):
            print("我是 类方法")
    
    
    f = Foo('yk')
    print(f.myself)  # <bound method Foo.myself of <__main__.Foo object at 0x000002B28FB59A90>>
    f.myself()  # 我是 yk
    
    print(Foo.clss)  # <bound method Foo.clss of <class '__main__.Foo'>>
    Foo.clss()  # 我是 类方法
    
    f.clss()  #对象也可以调用,但是默认传的第一个参数仍然是类

    二、非绑定方法

    不与类或对象绑定,类和对象都可以调用,但是不会自动传值。就是一个普通工具而已
    注意:
    与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,可不是普通函数,对象调用该方法会自动传值,而staticmethod装饰的方法,不管谁来调用,都没有自动传值一说

    class Foo:
        def __init__(self, name):
            self.name = name
    
        @staticmethod
        def stat(s1, s2):
            print(s1+s2)
    
    f = Foo('yk') 
    print(f.stat) # <function Foo.stat at 0x000001F59F6B5B70>  它就是一个普通的函数而已
    f.stat("hello ","yk") # hello yk 

    3.反射

    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。


    python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

    # 自省方法
    class Foo:
        def __init__(self, name):
            self.name = name
    
        def test(self):
            print("test.....")
    
    
    f = Foo("yk")
    # 检测是否含有某属性
    print(hasattr(f, 'name'))  # True
    print(hasattr(f, 'age'))  # False
    
    # 获取属性,如果没有就返回第三个参数设置的值
    print(getattr(f, 'name', "没有这个属性"))  # yk
    
    # 设置属性
    setattr(f, 'age', 18)
    print(f.age)  # 18
    
    # 删除属性
    delattr(f, 'name')
    print(hasattr(f, 'name'))  # False
    # 我们可以模拟一个把控制权暂时交给用户的实现
    class Demo:
    
        def __init__(self):
            self.cmd()
    
        def cmd(self):
            while True:
                # 用户输入一个已知命令
                cmd = input("cmd=>>>").strip()
                # 如果有这个属性
                if hasattr(self, cmd):
                    # 获取该属性
                    arg = getattr(self, cmd)
                    # 执行相应命令
                    arg()
                else:
                    break
    
        def get(self):
            print("get.....")
        
        def put(self):
            print("put.....")
    
    d = Demo()
    
    # cmd=>>>get
    # get.....
    # cmd=>>>put
    # put.....
    # cmd=>>>p
  • 相关阅读:
    dede文章插入分页符不起作用,编辑器中出现分页符,导致文章显示不全
    dedecms 图集标签{dede:productimagelist} {dede:field name='imgurls'}&nbs
    dede织梦怎么修改description的字数
    dede 内容页文章标题显示不全的更改方法
    amazon company
    rapleaf
    nope
    数据库事务隔离级别与锁
    nosql=not only sql
    Lustre是开放源代码的集群文件系统
  • 原文地址:https://www.cnblogs.com/ykgo/p/9362892.html
Copyright © 2020-2023  润新知