鱼C论坛

 找回密码
 立即注册
查看: 563|回复: 13

疑问

[复制链接]
发表于 2024-4-10 10:52:44 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在视频里,说property属性对象提供了getter、setter和deleter三个方法,这些方法对应property()函数的三个参数接口,实际上是不是就是下面这三个?
def __get__(self, instance, owner):
        print(f'get~\nself -> {self}\ninstance -> {instance}\nowner -> {owner}')
def __set__(self, instance, value):
        print(f'set~\nself -> {self}\ninstance -> {instance}\nvalue -> {value}')
def __delete__(self, instance):# 不要混淆__del__()
        print(f'delete~\nself -> {self}\ninstance -> {instance}')

@FishC
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-4-10 10:53:06 | 显示全部楼层
是的,`property`属性对象提供了getter、setter和deleter三个方法,并且这三个方法对应`property()`函数的三个参数接口。

- `__get__(self, instance, owner)`:用于获取属性值。当我们通过实例访问属性时,会调用该方法,并将实例对象和类对象作为参数传入。
- `__set__(self, instance, value)`:用于设置属性值。当我们通过实例给属性赋值时,会调用该方法,并将实例对象和要赋的值作为参数传入。
- `__delete__(self, instance)`:用于删除属性值。当我们通过del语句删除属性时,会调用该方法,并将实例对象作为参数传入。

这些方法可以通过`property()`函数创建属性对象后,使用装饰器语法`@`将其绑定到属性上,从而实现属性的自定义行为。

以下是一个简单示例:
class MyClass:
    def __init__(self):
        self._x = None
    
    @property
    def x(self):
        return self._x
    
    @x.setter
    def x(self, value):
        self._x = value
    
    @x.deleter
    def x(self):
        del self._x


obj = MyClass()
obj.x = 10  # 调用 __set__ 方法
print(obj.x)  # 调用 __get__ 方法,输出 10
del obj.x  # 调用 __delete__ 方法

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-10 11:02:29 | 显示全部楼层
class MyClass:
    def __init__(self):
        self._x = None
   
    @property
    def x(self):
        return self._x
   
    @x.setter
    def x(self, value):
        self._x = value
   
    @x.deleter
    def x(self):
        del self._x
这里的为啥不是@x.__set__(self, instance, value)
和@x.__delete__(self, instance)?
@FishC
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-10 11:02:47 | 显示全部楼层
亦又 发表于 2024-04-10 11:02
class MyClass:
    def __init__(self):
        s ...


好问题!在Python中,使用@property装饰器可以将一个类的方法转换为属性。当我们使用@property装饰器时,实际上是在创建一个名为x的属性,并提供getter和setter方法。

关于你的问题,为什么不是@x.__set__(self, instance, value)和@x.__delete__(self, instance)?

@property装饰器为我们封装了这个过程,所以我们不需要直接使用@x.__set__和@x.__delete__方法。相反,我们只需要定义带有特殊名称的方法(如上面的x.setter和x.deleter),然后将它们与属性相关联。这种方式更简洁和易读。

@property 装饰器会将 getter 方法与原始属性关联起来,使得当我们访问属性时,实际上是调用 getter 方法。类似地,@x.setter 装饰器会将 setter 方法与属性关联起来,使得当我们设置属性时,实际上是调用 setter 方法。同样,@x.deleter 装饰器会将 deleter 方法与属性关联起来,使得当我们删除属性时,实际上是调用 deleter 方法。

使用@property装饰器可以使代码更加整洁,易于维护。同时,它还允许我们在获取、设置或删除属性时执行自定义的逻辑。很方便对吧!

下面是一个使用@property装饰器的例子:
class MyClass:
    def __init__(self):
        self._x = None
   
    @property
    def x(self):
        return self._x
   
    @x.setter
    def x(self, value):
        self._x = value
   
    @x.deleter
    def x(self):
        del self._x

# 使用示例:
obj = MyClass()
obj.x = 10  # 设置属性值
print(obj.x)  # 获取属性值

del obj.x  # 删除属性
print(obj.x)  # 属性已经被删除,输出 None

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-10 11:37:53 | 显示全部楼层
class MYPropertyL:
    def __init__(self, fget=None, fset=None, fdel=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
    def __get__(self, instance, owner):
        return self.fget(instance)
    def __set__(self, instance, value):
        self.fset(instance, value)
    def __delete__(self, instance):
        self.fdel(instance)
    def getter(self, func):
        self.fget = func
        return self
    def setter(self, func):
        self.fset = func
        return self
    def deleter(self, func):
        self.fdel = func
        return self
在getter(self, func) deleter(self, func) 和setter(self, func)里,为什么还要都return self?
@FishC
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-10 11:38:08 | 显示全部楼层
亦又 发表于 2024-04-10 11:37
class MYPropertyL:
    def __init__(self, fget=No ...


在这个类中,getter、setter和deleter都是用来设置相应的方法的装饰器。当我们使用这些装饰器时,实际上是将对应的方法传递给了fget、fset和fdel属性。

为什么要返回self呢?其实在这里返回self是为了实现链式调用。当我们在使用装饰器时,可以像下面这样连续使用多个装饰器:
class MyClass:
    @MYPropertyL()
    def my_attr(self):
        ...

    @my_attr.getter
    def my_attr(self):
        ...

    @my_attr.setter
    def my_attr(self):
        ...

    @my_attr.deleter
    def my_attr(self):
        ...

如果我们在getter、setter和deleter中不返回self,那么在调用完一个装饰器后,就无法再次使用另一个装饰器了。因为没有返回self,所以返回的值是None,None对象没有getter、setter和deleter方法,所以会报错。

通过返回self,我们可以保证在使用装饰器时,可以一直进行链式调用,让代码变得更加简洁和清晰。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-10 15:25:45 | 显示全部楼层
class PropertyL:
    def __init__(self, fget=None, fset=None, fdel=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
    def __get__(self, instance, owner):
        return self.fget(instance)
    def __set__(self, instance, value):
        self.fset(instance, value)
    def __delete__(self, instance):
        self.fdel(instance)
    def getter(self, func):
        self.fget = func
        return self
    def setter(self, func):
        self.fset = func
        return self
    def deleter(self, func):
        self.fdel = func
        return self
是不是通过装饰器   修改了    self.fget  self.fset   self.fdel 属性值并将其变成了函数,再通过
    def __get__(self, instance, owner):
        return self.fget(instance)
    def __set__(self, instance, value):
        self.fset(instance, value)
    def __delete__(self, instance):
        self.fdel(instance)
这几个三个函数的触发条件,才形成对拦截对象属性的读取、写入和删除操作

@FishC
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-10 15:25:59 | 显示全部楼层
亦又 发表于 2024-04-10 15:25
class PropertyL:
    def __init__(self, fget=None ...


是的,这段代码通过装饰器的方式修改了属性的获取、设置和删除操作。通过调用getter、setter和deleter函数,我们可以将传入的函数赋值给fget、fset和fdel属性,从而实现对属性操作的拦截。

在使用PropertyL类的时候,我们可以通过下面的方式定义一个属性:
class MyClass:
    @PropertyL()
    def my_property(self):
        # 这里是属性的具体实现

其中,@PropertyL()是PropertyL类的实例化,它接受三个可选参数:fget、fset和fdel,分别表示获取、设置和删除属性的函数。通过在属性的定义上加上这个装饰器,实际上相当于将my_property属性变成了一个特殊的属性,它将调用上述定义的函数来完成属性的读取、写入和删除操作。

例如,我们可以这样使用这个特殊的属性:
obj = MyClass()
obj.my_property = 10  # 调用setter函数将属性设置为10
print(obj.my_property)  # 调用getter函数获取属性的值,输出10
del obj.my_property  # 调用deleter函数删除属性

需要注意的是,这里的getter、setter和deleter函数都需要接受两个参数:instance表示属性所属的实例对象,value表示要设置的值(只有setter函数需要)。这样,我们在函数内部就可以自由地访问和操作属性了。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-10 15:35:03 | 显示全部楼层

class PropertyL:
    def __init__(self, fget=None, fset=None, fdel=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
    def __get__(self, instance, owner):
        return self.fget(instance)
    def __set__(self, instance, value):
        self.fset(instance, value)
    def __delete__(self, instance):
        self.fdel(instance)
    def getter(self, func):
        self.fget = func
        return self
    def setter(self, func):
        self.fset = func
        return self
    def deleter(self, func):
        self.fdel = func
        return self
是不是通过装饰器   修改了    self.fget  self.fset   self.fdel 属性值并将其变成了函数?

再去执行对拦截对象属性的读取、写入和删除操作的是
    def __get__(self, instance, owner):
      
    def __set__(self, instance, value):
      
    def __delete__(self, instance):
是上面这三个?
   
def getter(self, func):

def setter(self, func):
   
def deleter(self, func):
还是什么这三个?
@FishC
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-10 15:35:18 | 显示全部楼层
亦又 发表于 2024-04-10 15:35
class PropertyL:
    def __init__(self, fget=None ...


是的,通过使用装饰器修改了self.fget、self.fset和self.fdel属性的值,并将它们变成了函数。

对于拦截对象属性的读取、写入和删除操作,你提到的三个方法是正确的:

- `__get__(self, instance, owner)`:用于拦截对属性的读取操作。
- `__set__(self, instance, value)`:用于拦截对属性的写入操作。
- `__delete__(self, instance)`:用于拦截对属性的删除操作。

而`getter(self, func)`、`setter(self, func)`和`deleter(self, func)`是辅助方法,用于设置相应的拦截方法。

例如,你可以这样使用PropertyL类:
class MyClass:
    @PropertyL()
    def my_property(self):
        return self._my_property

    @my_property.setter
    def my_property(self, value):
        self._my_property = value

    @my_property.deleter
    def my_property(self):
        del self._my_property

这样,当你对my_property进行读取、写入和删除操作时,就会调用相应的拦截方法来处理。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-10 15:38:07 | 显示全部楼层
上面的读取、写入和删除操作触发条件有哪些?
@FishC
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-10 15:38:18 | 显示全部楼层
亦又 发表于 2024-04-10 15:38
上面的读取、写入和删除操作触发条件有哪些?
@FishC


对于读取操作:
1. 打开一个文件,使用读取模式(如'r'或'rb')。
2. 使用read()方法读取文件中的内容。
3. 关闭文件。

对于写入操作:
1. 打开一个文件,使用写入模式(如'w'或'wb')。
2. 使用write()方法向文件中写入内容。
3. 关闭文件。

对于删除操作:
1. 使用os模块中的remove()函数。
2. 指定要删除的文件路径作为参数,调用remove()函数。

需要注意的是,在进行任何文件操作之前,需要确保文件已经存在。在使用write()方法写入文件时,若文件不存在,则会创建一个新文件。而在使用remove()函数删除文件时,若文件不存在,则会引发FileNotFoundError异常。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-10 15:40:36 | 显示全部楼层
- `__get__(self, instance, owner)`:用于拦截对属性的读取操作。
- `__set__(self, instance, value)`:用于拦截对属性的写入操作。
- `__delete__(self, instance)`:用于拦截对属性的删除操作。


上面的读取、写入和删除操作触发条件有哪些?
@FishC
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-10 15:40:45 | 显示全部楼层
亦又 发表于 2024-04-10 15:40
- `__get__(self, instance, owner)`:用于拦截对属性 ...


读取、写入和删除操作触发条件如下所示:

读取操作触发条件:
- 当实例对象通过点号`.`访问属性时,会触发`__get__`方法。

写入操作触发条件:
- 当实例对象通过点号`.`给属性赋值时,会触发`__set__`方法。

删除操作触发条件:
- 当实例对象通过`del`关键字删除属性时,会触发`__delete__`方法。

需要注意的是,上述方法是实现描述符(descriptor)的类中定义的特殊方法,用于拦截对属性的操作。当一个类中的属性被定义为描述符时,我们可以在描述符类中定义这些方法,在对属性进行读取、写入或删除时,相应的方法就会被调用。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-23 08:15

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表