【问题标题】:"Sub-classes" and self in PythonPython中的“子类”和自我
【发布时间】:2013-11-08 04:08:39
【问题描述】:

注意:我发现在询问如何做之前,我需要更清楚地弄清楚我希望每个属性/描述符/类/方法做什么!我认为我的问题目前无法回答。谢谢大家帮助我。

感谢 icktoofay 和 BrenBarn,我开始了解量词和属性,但现在我要问一个稍微难一点的问题:

我现在看到了这些是如何工作的:

class Blub(object):
    def __get__(self, instance, owner):
        print('Blub gets ' + instance._blub)
        return instance._blub

    def __set__(self, instance, value):
        print('Blub becomes ' + value)
        instance._blub = value

class Quish(object):
    blub = Blub()

    def __init__(self, value):
        self.blub = value

以及 a = Quish('one') 的工作原理(产生“Blub 成为一体”),但请看一下这段代码:

import os
import glob

class Index(object):
    def __init__(self, dir=os.getcwd()):
        self.name = dir    #index name is directory of indexes
        # index is the list of indexes
        self.index = glob.glob(os.path.join(self.name, 'BatchStarted*'))
        # which is the pointer to the index (index[which] == BatchStarted_12312013_115959.txt)
        self.which = 0
        # self.file = self.File(self.index[self.which])
    def get(self):
        return self.index[self.which]
    def next(self):
        self.which += 1
        if self.which < len(self.index):
            return self.get()
        else:
            # loop back to the first
            self.which = 0
            return None
    def back(self):
        if self.which > 0:
            self.which -= 1
        return self.get()

class File(object):
    def __init__(self, file):
        # if the file exists, we'll use it.
        if os.path.isfile(file):
            self.name = file
        # otherwise, our name is none and we return.
        else:
            self.name = None
            return None
        # 'file' attribute is the actual file object
        self.file = open(self.name, 'r')
        self.line = Lines(self.file)

class Lines(object):
    # pass through the actual file object (not filename)
    def __init__(self, file):
        self.file = file
        # line is the list if this file's lines
        self.line = self.file.readlines()
        self.which = 0
        self.extension = Extension(self.line[self.which])
    def __get__(self):
        return self.line[self.which]
    def __set__(self, value):
        self.which = value
    def next(self):
        self.which += 1
        return self.__get__()
    def back(self):
        self.which -= 1
        return self.__get__()

class Extension(object):
    def __init__(self, lineStr):
        # check to make sure a string is passed
        if lineStr:
            self.lineStr = lineStr
            self.line = self.lineStr.split('|')
            self.pathStr = self.line[0]
            self.path = self.pathStr.split('\\')
            self.fileStr = self.path[-1]
            self.file = self.fileStr.split('.')
        else:
            self.lineStr = None                    
    def __get__(self):
        self.line = self.lineStr.split('|')
        self.pathStr = self.line[0]
        self.path = self.pathStr.split('\\')
        self.fileStr = self.path[-1]
        self.file = self.fileStr.split('.')
        return self.file[-1]
    def __set__(self, ext):
        self.file[-1] = ext
        self.fileStr = '.'.join(self.file)
        self.path[-1] = fileStr
        self.pathStr = '\\'.join(self.path)
        self.line[0] = self.pathStr
        self.lineStr = '|'.join(self.line)

首先,这里可能有一些拼写错误,因为我一直在处理它,并且半信半疑。那不是我的意思。我的观点是,在 icktoofay 的示例中,没有任何内容传递给 Blub()。有什么办法可以做我在这里做的事情,即设置一些“自我”属性,然后在进行一些处理后,将其传递给下一个班级?这会更适合房产吗?

我想要这样:

>>> i = Index()         # i contains list of index files
>>> f = File(i.get())   # f is now one of those files
>>> f.line
'\\\\server\\share\\folder\\file0.txt|Name|Sean|Date|10-20-2000|Type|1'
>>> f.line.extension
'txt'
>>> f.line.extension = 'rtf'
>>> f.line
'\\\\server\\share\\folder\\file0.rtf|Name|Sean|Date|10-20-2000|Type|1'

【问题讨论】:

  • 你的思想实验,也许:f.linestr 还是 Lines?如果您向Lines 添加(例如)find 方法,您会期望f.line.find() 调用strfind 实现还是Linesfind 实现?为什么?
  • 我更新了我的问题,以反映我对我正在尝试做的事情的模棱两可的认识。在我开始询问如何在其中做一些事情之前,我需要确定我希望程序如何工作。

标签: python descriptor


【解决方案1】:

你可以这样做,但问题不是关于属性/描述符,而是更多关于创建提供你想要的行为的类。

所以,当您执行f.line 时,这是一个对象。当您执行f.line.extension 时,即执行(f.line).extension --- 也就是说,它首先评估f.line,然后获取extension 的任何f.line 的属性。

这里重要的是,f.line 无法知道您以后是否会尝试访问它的extension。所以你不能让f.line 为“普通”f.line 做一件事,而为f.line.extension 做另一件事。 f.line 部分必须在两者中相同,extension 部分不能改变这一点。

您似乎想要做的解决方案是让f.line 返回某种对象,该对象在某种程度上看起来或工作起来像一个字符串,但也允许设置属性并相应地更新自身。究竟如何做到这一点取决于您需要多少 f.lines 来表现得像一个字符串,以及您需要多少它来做其他事情。基本上,您需要 f.line 成为“看门人”对象,通过像字符串一样处理某些操作(例如,您显然希望它作为字符串 display),并以自定义方式处理其他对象(例如,您显然希望能够在其上设置 extension 属性并更新其内容)。

这是一个简单的例子:

class Line(object):
    def __init__(self, txt):
        self.base, self.extension = txt.split('.')

    def __str__(self):
        return self.base + "." + self.extension

现在你可以这样做了:

>>> line = Line('file.txt')
>>> print line
file.txt
>>> line.extension
'txt'
>>> line.extension = 'foo'
>>> print line
file.foo

但是,请注意我做了print line,而不仅仅是line。通过编写__str__ 方法,我定义了当您执行print line 时发生的行为。但是如果你在不打印它的情况下评估它是“原始的”,你会发现它并不是一个真正的字符串:

>>> line
<__main__.Line object at 0x000000000233D278>

你也可以覆盖这个行为(通过定义__repr__),但是你想要吗?这取决于你想如何使用line。关键是你需要决定你想让你的line在什么情况下做什么,然后设计一个可以做到这一点的类。

【讨论】:

  • 我可能最终会使用 __str__() 函数。这看起来很棒,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多