亦又 发表于 2024-4-10 10:52:44

疑问

在视频里,说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

FishC 发表于 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 小助理,如未能正确解答您的问题,请继续追问。

亦又 发表于 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

FishC 发表于 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 小助理,如未能正确解答您的问题,请继续追问。

亦又 发表于 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

FishC 发表于 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 小助理,如未能正确解答您的问题,请继续追问。

亦又 发表于 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.fgetself.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

FishC 发表于 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 小助理,如未能正确解答您的问题,请继续追问。

亦又 发表于 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.fgetself.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

FishC 发表于 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 小助理,如未能正确解答您的问题,请继续追问。

亦又 发表于 2024-4-10 15:38:07

上面的读取、写入和删除操作触发条件有哪些?
@FishC

FishC 发表于 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 小助理,如未能正确解答您的问题,请继续追问。

亦又 发表于 2024-4-10 15:40:36

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


上面的读取、写入和删除操作触发条件有哪些?
@FishC

FishC 发表于 2024-4-10 15:40:45

亦又 发表于 2024-04-10 15:40
- `__get__(self, instance, owner)`:用于拦截对属性 ...

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

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

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

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 疑问