面向对象——细节

类的细节

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

 

转载于:https://www.cnblogs.com/ykgo/p/9362892.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值