Discuss / Python / 交作业,附带提问为什么要加_

交作业,附带提问为什么要加_

Topic source

class Screen(object): @property def width(self): return self._width

@property
def height(self):
    return self._height

@property
def resolution(self):
    return self._width*self._height

@width.setter
def width(self,value):
    if not isinstance(value, (int)):
        raise ValueError('score must be an integer!')
    self._width = value

@height.setter
def height(self,value):
    if not isinstance(value, (int)):
        raise ValueError('score must be an integer!')
    self._height = value

为什么一定要写成self.width,去掉就会报错呢?

多背单词

#2 Created at ... [Delete] [Delete and Lock User]

同问,为什么要加

##self._width 里面的

##_

哥,你这加了##我更不明白了呀

帖子较长,纪念第一次发帖,求大神轻怼。错误和原因分析

#!/usr/bin/env python3

-- coding: utf-8 --

class Screen(object): @property def width(self): return self.width @width.setter def width(self,value): self.width=value

@property
def height(self):
    return self.height

@height.setter
def height(self,value):
    self.height=value

@property
def resolution(self):
    self.resolution=self.width*self.height
    return self.resolution

测试:直接加s.width进行测试

s.width

#s.width = 1024

#s.height = 768

#print('resolution =', s.resolution)

#if s.resolution == 786432:

print('测试通过!')

#else:

print('测试失败!')

调试出错 Traceback (most recent call last): File "D:/Pycharm projects/ex/ex1", line 25, in <module> s.width File "D:/Pycharm projects/ex/ex1", line 6, in width return self.width File "D:/Pycharm projects/ex/ex1", line 6, in width return self.width File "D:/Pycharm projects/ex/ex1", line 6, in width return self.width [Previous line repeated 495 more times] RecursionError: maximum recursion depth exceeded Process finished with exit code 1 查了具体意思,是超过了最大递归深度。 重复了495次的代码

def width(self): return self.width 可理解为执行s.width,可提取加了装饰器后的实例属性。返回值仍是s.width,因此继续递归,直到超过最大递归深度报错。 可修改为任意非self.width的变量名 例如self.www class Screen(object): @property def width(self): return self.www @width.setter def width(self,value): self.www=value 我的代码执行后又出现了问题,由于测试中加了s.width Traceback (most recent call last): File "D:/Pycharm projects/ex/ex1", line 22, in <module> s.width File "D:/Pycharm projects/ex/ex1", line 4, in width return self._width AttributeError: 'Screen' object has no attribute 'www' 可理解为实例尚未得到www这个属性,Screen对象里没有www。放到s.width(1024)后, 可正常执行。也会有人问为什么最后的s.resolution可以直接用,只是因为它的属性来自于width和height前两个属性。 可以尝试将它移动到s.width(1024)或s.height(768)之前,会显示缺少属性width或者height。菜鸟初次发帖,多多指教,附上修改后的代码和测试结果。 class Screen(object): @property def width(self): return self.www @width.setter def width(self,value): self.www=value

@property
def height(self):
    return self.hhh

@height.setter
def height(self,value):
    self.hhh=value

@property
def resolution(self):
    self.ppp=self.www*self.hhh
    return self.ppp

s = Screen() s.width = 1024 print(s.width) s.height = 768 print(s.height) print(s.resolution) print('resolution =', s.resolution) if s.resolution == 786432: print('测试通过!') else: print('测试失败!') 测试结果 1024 768 786432 resolution = 786432 测试通过!

Process finished with exit code 0

不加_会显示报错,同样对于装饰器懵逼,但在类和实例中不加装饰器也有同样的思考。 class Student(object): def init(self, name, score): self.name = name self.score = score def get_name(self): return self.get_name def get_score(self): return self.score s=Student('Bart Simpson', 59) print(s.get_name()) print(s.get_score()) 测试结果很明显,s.get_name()返回的是一个方法,s.get_score()返回的是值。 D:\Anaconda3\envs\ay\python.exe "D:/Pycharm projects/ex/ex1"

<bound method Student.get_name of <__main__.Student object at 0x0000029F4D348400>> 59 Process finished with exit code 0 原因就在于 def get_name(self): return self.get_name中返回的就是一个函数,以后可以记住了在用到类中的方法时,要注意类中变量的定义,不能一致,否则返回的是函数。更有趣的是,当加了括号print((s.get_score()))再次调用的结果 D:\Anaconda3\envs\ay\python.exe "D:/Pycharm projects/ex/ex1"

<bound method Student.get_name of <__main__.Student object at 0x00000239BD518400>> 59 Process finished with exit code 0 返回的方法内存中存储地址再次改变,类似于无限递归。

不一定是非要加 下划线'_', 而是要返回的属性名不能与装饰器修饰的 函数名一致 如下

@hello.setter
def hello(self, hello):
      print('x')
    self.hello = hello

该段代码中 self.hello = hello 这一条语句一旦执行,就相当于再一次调用了函数属性hello,并进入函数hello中,陷入了死循环,结果就是无限输出x,然后函数调用栈溢出,程序被强制结束报错

如果,将self.hello 改为self.h 或self._hello 等任意不与该函数同名的变量名,程序即可正常执行并结束

小喵biubiu

#7 Created at ... [Delete] [Delete and Lock User]

怎么说呢,@property和@width.setter这两个下面的值。 其中@property下面的 return self.width,这个width前面加不加下划线都不会报错。但是@width.setter下面的 self.'下划线'width = value 这个width前必须加下划线,具体为什么暂时还没明白,随后再慢慢查,明白了再来说。

可能私有属性才有get,set方法吧

我同意人见人爱的ziyo说的,确实只要返回的变量名与@property下def函数名不一致即可。下面这段代码是对的 class Screen(object): @property def width(self): return self.wid @width.setter def width(self,value): if not isinstance(value,int): raise ValueError('width must be an integer!') self.wid=value


  • 1

Reply