Python - 通常如何使用递归方法将实例变量作为隐式参数传递给方法

2024-02-24

我在将对象的实例变量传递给实例方法时遇到问题。

我在其他地方搜索过这个,但我一直找到的只是有关如何使用对象将对象传递给方法的信息self,我已经知道了,或者只是关于类和实例方法之间的一般差异的教程,但没有具体回答我的问题。我的问题的答案肯定存在于某个地方,我想我只是不知道实际要问什么。

在我的代码中,我有这个类:

class SongData:

    def __init__(self, datapoint):
        self.artist = datapoint['artist']
        self.track = datapoint['name']

    def xtradata_rm(self, regex, string=None):
        if string is None:
            string = self
        srchrslts = re.search(regex, string)
        if srchrslts is not None:
            if regex == 'f.*?t':
                self = self.replace(string,'')
                self.xtradata_rm('\((.*?)\)')
            else:
                self.xtradata_rm('f.*?t', srchrslts)

    def example_method(self):
        #This one isn't actually in the code, included for ease of explanation.
        print(self) 

    #some more methods irrelevant to question down here.

想象一下我们通过执行以下操作来实例化一个对象song = SongData(datapoint)。方法xtradata_rm应该搜索song.artist or song.track括号中的部分的字符串,那么如果找到的部分包含任何形式的单词“featuring”,请将其从字符串中删除,然后重试,直到找不到更多带有包含“featuring”的括号的括号表达式。

我现在知道这可能是 100% 错误的 self 用法,但我不知道应该用什么来代替它来实现我想要的行为。那么在我的脚本中我尝试这样做:

file_list = glob.glob("*procData.json")


for datafname in file_list:
    datafile = json.load(open(datafname))

    for i, datapoint in enumerate(datafile['EnvDict']):
        song = SongData(datapoint)
        song.track.xtradata_rm('\((.*?)\)')
        song.releasefetch(lfmapi)
        song.dcsearcher(dcapi)
        datapoint.update({"album": song.release, "year": song.year})

    with open("upd" + datafname, 'w') as output:
        json.dump(datafile, output)

但后来我得到这个错误:

Traceback (most recent call last):
    song.track.xtradata_rm('\((.*?)\)')
AttributeError: 'str' object has no attribute 'xtradata_rm'

如果我注释掉该行,代码就会运行。

所以我的第一个问题是,一般来说,我必须做什么才能去song.track.example_method() or song.artist.example_method()并得到track_name or artist_name分别按预期打印在控制台中。

我的第二个问题是,我怎样才能做同样的事情xtradata_rm(IE。 能够做song.track.xtradata_rm('\((.*?)\)')并基本上插入song.track代替self在方法内),以及如何xtradata_rm递归并尝试将实例变量隐式传递给自身会改变事情吗?


看起来你想添加方法xtradata_rm to str物体self.artist and self.track.

你对 Python 的误解之一是,不能通过给变量赋值来改变你的对象self(或任何其他变量)。self = 123不改变名称后面的对象self to 123,它使名字self指向对象123(并且仅在当前范围内执行)。

要真正获得这种区别,您应该观看演讲关于 Python 名称和值的事实和神话 https://www.youtube.com/watch?v=_AEJHKGk9ns作者:内德·巴切尔德。

另一件事是str对象是不可变的,因此即使名称按您的预期工作,您也无法修改str。例如,bytearray是可变的,并且str不是,看看区别:

In [1]: b = bytearray(b'My example string')

In [2]: id(b)
Out[2]: 4584776792

In [3]: b[3:10] = b'modified'

In [4]: b
Out[4]: bytearray(b'My modified string')

In [5]: id(b) # same object
Out[5]: 4584776792

In [6]: s = 'My example string'

In [7]: s[3:10] = 'modified'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-22fe89ae82a3> in <module>()
----> 1 s[3:10] = 'modified'

TypeError: 'str' object does not support item assignment

In [8]: new_s = s.replace('example', 'modified')

In [9]: id(new_s) # different object
Out[9]: 4584725936

In [10]: id(s)
Out[10]: 4584762296

In [11]: s # original string unmodified
Out[11]: 'My example string'

因此,为了实现您的方法,我们需要创建包装器str看起来像的物体str并表现得像str,但也实现了你的方法。由于许多复杂的原因,这可能相当困难,在 python 中代理对象是一次真正的考验 http://code.activestate.com/recipes/496741-object-proxying/.

但不要害怕!在标准库的深处有一个类(144行无聊的代码 https://github.com/python/cpython/blob/e2e7ff0d0378ba44f10a1aae10e4bee957fb44d2/Lib/collections/__init__.py#L1098) 只为你:集合.UserString https://docs.python.org/3.6/library/collections.html#collections.UserString.

我们需要做的就是对其进行子类化并在其上实现您的方法:

class SongAttribute(collections.UserString):
    def example_mutate(self):
        """Works UNLIKE other string methods, mutates SongAttribute object,
        but I think this is how you want your code to work. Jugging just a bit ;) 
        Note: actual str object still is immutable and wasn't mutated,
        self.data now just references another immutable str object.

        P.S.: self.data is the object being proxied by UserString class
        """

        self.data = self.data.replace(' ', '_')
        return self

    def example_return_new(self):
        """Works like all other string metods, returns new string"""
        return self.replace(' ', '_')

song = SongAttribute('My Song Name') # creating new song attribute (artist or track)
print(song, type(song)) # it looks like str, but isn't
print(song.upper(), type(song.upper())) # it has all of the str methods, but they return SongAttribute objects, not str objects.

# Return new
print()
new_song = song.example_return_new()
print(new_song, type(new_song)) # we got underscored SongAttribute

# Mutate
print()
print(song, type(song))
print(song.example_mutate(), type(song.example_mutate())) # this method changed song object internally
print(song, type(song)) # and now we still see the changes

Output:

My Song Name <class '__main__.SongAttribute'>
MY SONG NAME <class '__main__.SongAttribute'>

My_Song_Name <class '__main__.SongAttribute'>

My Song Name <class '__main__.SongAttribute'>
My_Song_Name <class '__main__.SongAttribute'>
My_Song_Name <class '__main__.SongAttribute'>

现在你可以在上面实现你的方法SongAttribute,并改变SongData构造函数:

def __init__(self, datapoint):
    self.artist = SongAttribute(datapoint['artist'])
    self.track = SongAttribute(datapoint['name'])
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python - 通常如何使用递归方法将实例变量作为隐式参数传递给方法 的相关文章

随机推荐

  • 如何在Firebase Analytics中为Flutter Web设置用户属性?

    我在用这个包 https github com FirebaseExtended firebase dart 版本7 2 1 在一些flutter web项目中 我需要在firebase分析中设置一些用户属性 顺便说一句 感谢这个答案 ht
  • Android:系统资源和应用程序资源之间的区别? [复制]

    这个问题在这里已经有答案了 来自 Android 文档Resources class public static Resources getSystem 添加到 API 级别 1 返回一个全局共享资源对象 仅提供对系统资源的访问 无应用程序
  • 表格中的额外宽度如何在各列之间划分?

    今天我想知道 HTML 表格中的多余空间 超出内容所请求的范围 是如何在各列之间分割的 令人惊讶的是 即使经过大量谷歌搜索 我也找不到答案 所以我很快就模拟了最简单的页面并对其进行了测试 table width 500 tr td div
  • ILSpy,如何解决依赖关系?

    我想用 ILSpy 反汇编整个 NET 程序集 我使用这段代码作为基础 http skysigal xact solutions com Blog tabid 427 entryid 2488 Default aspx http skysi
  • 如何使用需要从命令提示符/批处理文件引用的参数来调用 PowerShell Start-Process 命令?

    我在尝试执行一个命令时收到此错误PowerShell 我在尝试着exec这个命令 powershell exe Start Process FilePath C Windows System32 attrib h s CD Verb run
  • 为什么我的终端不能正确输出 unicode 字符?

    例如 我的终端是这样做的 echo e xE2 x98 xA0 我希望它能做到这一点 echo e xE2 x98 xA0 为什么 如何让我的终端输出正确的 unicode 符号 我在 Arch Linux 上使用 Gnome 3 的终端
  • 纠正使用 jQuery 动画文本不透明度时的 IE Cleartype/Filter 问题

    大家好 我遇到了一个 IE 问题 这似乎是一个众所周知 常见的错误 我有一个用 jQuery 构建的图像幻灯片 可以在其他浏览器中完美运行 然而 在 IE 中 我遇到了一个问题 即幻灯片运行一次后文本就会消除锯齿 也就是说 如果幻灯片中有三
  • Chrome 扩展:chrome.storage 未定义

    我将以下代码添加到我的其他工作的 Google Chrome 扩展中 var storage chrome storage console log storage is storage var bookmarks chrome bookma
  • 使用 awk 和变量正则表达式提取两个模式之间的行

    我正在寻找一种方法来使用 awk 提取两个模式之间的行 变量 每个部分结束于下一个部分的开始处 示例文件 SECTION 1 info 1 info 2 info 3 SECTION 2 info 4 info 5 info 6 SOMET
  • 从 .gitmodules 恢复 git 子模块

    我有一个文件夹 它是一个 git 存储库 它包含一些文件和 gitmodules 文件 现在 当我这样做时git init进而git submodule init 后面的命令输出什么也没有 如何帮助 git 查看 gitmodules 文件
  • sympy 将分数与变量分开

    使用 sympy 如何将分数与变量分开 Mul Fraction 3 5 Pow K Integer 2 2 3 K 5 to 3 2 K 5 我知道这个简化版本还不错 但是当我有很大的方程时 它会变得混乱 我不太熟悉漂亮的打印或 LaTe
  • Maven 过滤

    我正在使用 Maven 3 x 在 Hudson 中构建 Android 应用程序 作为构建的一部分 我使用过滤 配置文件对 strings xml 文件进行文本替换 因此 在 strings xml 中 我将包含以下条目
  • 3D 绘图中 y 轴和 z 轴的交换位置

    默认情况下 在 3D 中绘制一组点 或其他内容 matplotlib 找到z垂直轴 如下所示 代码如下 我需要交换z and y轴 使得y轴垂直显示 我环顾四周但找不到办法告诉matplotlib去做这个 Add 我不想诉诸于交换数据和标签
  • 好友列表:关系数据库表设计

    所以 好友列表的现代概念是 假设我们有一个名为 Person 的表 现在 该 Person 需要有许多好友 其中每个好友也属于 person 类 构建关系最明显的方法是通过连接表 IE buddyID person1 id person2
  • Shiny布局,是否可以在Shiny中拥有左侧和骑侧边栏布局?

    在 Shiny 中可以有这样的布局吗 我理想地想要一个左侧和右侧边栏 我已经看到了一些解决方案shinydashboardPlus但这不正是我所追求的 我有一个与此示例结构类似的应用程序 mychoices lt c pick me A p
  • 如何在此处的集群地图中显示重复的制造商

    我在这里使用地图并使用聚类 但我在显示坐标相同 dublicate 的制造商时遇到问题 当我放大聚类时 不幸的是 制造商不可见 但聚类仍然可见 当集群缩放时如何显示这些标记 我的集群选项如下 var clusteredDataProvide
  • 使用 Rails5 和 ActionCable 时不允许请求来源:http://localhost:3001

    Rails 5 0 0 beta2 中尝试使用 ActionCable 的应用程序出现服务器问题 使用 localhost 3000 效果很好 因为这是大多数 ActionCable 的默认设置 但是如果我尝试在端口 3001 上运行 Ra
  • 有没有办法在 Azure DevOps 中创建组织仪表板?

    我们的团队目前正在使用 DevOps 并对一切的运行情况感到非常满意 我们在每个项目中设置了仪表板来跟踪工作项和冲刺 并希望在组织级别执行相同的操作 有没有办法创建组织中多个项目的总体概述 不幸的是 我们无法创建组织级别的仪表板 它不受支持
  • 将颜色从 Javascript 传递到片段着色器

    我目前正在学习webgl 有一个问题 我正在尝试制作一个三角形并将颜色信息从 js 文件传递 到片段着色器中 以下是我的js代码 var VSHADER SOURCE attribute vec4 a Position n attribut
  • Python - 通常如何使用递归方法将实例变量作为隐式参数传递给方法

    我在将对象的实例变量传递给实例方法时遇到问题 我在其他地方搜索过这个 但我一直找到的只是有关如何使用对象将对象传递给方法的信息self 我已经知道了 或者只是关于类和实例方法之间的一般差异的教程 但没有具体回答我的问题 我的问题的答案肯定存