假设我在 python 中有一个简单的类
class Wharrgarbl(object):
def __init__(self, a, b, c, sum, version='old'):
self.a = a
self.b = b
self.c = c
self.sum = 6
self.version = version
def __int__(self):
return self.sum + 9000
def __what_goes_here__(self):
return {'a': self.a, 'b': self.b, 'c': self.c}
>>> w = Wharrgarbl('one', 'two', 'three', 6)
>>> int(w)
9006
>>> w = Wharrgarbl('one', 'two', 'three', 6)
>>> dict(w)
{'a': 'one', 'c': 'three', 'b': 'two'}
__dict__和 dict为 __what_goes_here__ ,但是 dict(w)导致 TypeError: Wharrgarbl object is not iterable在这两种情况下。我不认为简单地使类可迭代就可以解决问题。我还尝试了许多谷歌,其中包含尽可能多的不同措辞的“python cast object to dict”,但找不到任何相关内容:{w.__dict__不会做我想做的事,因为它会包含 w.version和 w.sum .我想自定义类型转换到dict以同样的方式,我可以将类型转换自定义为 int通过使用 def int(self) .>>> w.__what_goes_here__()
{'a': 'one', 'c': 'three', 'b': 'two'}
dict(w)工作,因为它与 int(w) 是同一类型的东西或 str(w) .如果没有更pythonic的方式,那也很好,只是想我会问。哦!我想因为这很重要,这适用于 python 2.7,但也适用于 2.4 旧的和破坏的解决方案。__dict__ 中的所有内容。包含在 dict() 返回的字典中.诸如公共(public)变量与私有(private)变量之类的东西可能足以解释我在寻找什么。这些对象将存储一些用于计算的值,因此我不需要/不想显示在结果字典中。asdict路线建议,但这是一个艰难的选择,选择我想成为问题的答案。 @RickTeachey 和@jpmc26 都提供了我将要采用的答案,但前者有更多信息和选项,并且也获得了相同的结果,并且获得了更多投票,所以我同意了。不过大家都点赞,感谢您的帮助。我在stackoverflow上潜伏了很长时间,我正试图让我的脚趾更多地浸入水中。
最佳答案
至少有五六种方式。首选方式取决于您的用例是什么。
选项 1:
只需添加一个 asdict()方法。
根据问题描述,我会非常考虑 asdict其他答案建议的做事方式。这是因为看起来您的对象并不是真正的集合:
class Wharrgarbl(object):
...
def asdict(self):
return {'a': self.a, 'b': self.b, 'c': self.c}
使用下面的其他选项可能会让其他人感到困惑,除非很明显哪些对象成员会和不会被迭代或指定为键值对。'typing.NamedTuple' 继承您的类(或大部分等效的 'collections.namedtuple' ),并使用 _asdict method为您提供。from typing import NamedTuple
class Wharrgarbl(NamedTuple):
a: str
b: str
c: str
sum: int = 6
version: str = 'old'
使用命名元组是一种非常方便的方法,可以轻松地为类添加大量功能,包括 an _asdict method .但是,一个限制是,如上所示,NT 将包括其 _asdict 中的所有成员。 ._asdict结果:from typing import NamedTuple
class Wharrgarbl(NamedTuple):
a: str
b: str
c: str
sum: int = 6
version: str = 'old'
def _asdict(self):
d = super()._asdict()
del d['sum']
del d['version']
return d
另一个限制是 NT 是只读的。这可能是也可能不是可取的。__iter__ .def __iter__(self):
yield 'a', self.a
yield 'b', self.b
yield 'c', self.c
现在你可以这样做:dict(my_object)
这是有效的,因为 dict()构造函数接受 (key, value) 的迭代成对构建字典。在执行此操作之前,问问自己是否以这种方式将对象作为一系列键值对进行迭代——同时方便创建 dict - 在其他情况下实际上可能是令人惊讶的行为。例如,问自己这个问题“list(my_object) 的行为应该是……?”obj["a"] 直接访问值语法不起作用,关键字参数解包也不起作用。对于那些,您需要实现映射协议(protocol)。dict不使用 __iter__ ,如果所有键都是字符串,还提供解包行为( {**my_obj} )和关键字解包行为( dict(**my_obj) )。keys()和 __getitem__ .class MyKwargUnpackable:
def keys(self):
return list("abc")
def __getitem__(self, key):
return dict(zip("abc", "one two three".split()))[key]
现在您可以执行以下操作:>>> m=MyKwargUnpackable()
>>> m["a"]
'one'
>>> dict(m) # cast to dict directly
{'a': 'one', 'b': 'two', 'c': 'three'}
>>> dict(**m) # unpack as kwargs
{'a': 'one', 'b': 'two', 'c': 'three'}
如上所述,如果您使用的是足够新的 python 版本,您还可以像这样将映射协议(protocol)对象解压缩到字典理解中(在这种情况下,您的键不需要是字符串):>>> {**m}
{'a': 'one', 'b': 'two', 'c': 'three'}
请注意,映射协议(protocol)优先于 __iter__将对象转换为 dict 时的方法直接(不使用 kwarg 解包,即 dict(m) )。因此,当用作可迭代对象(例如, list(m) )与转换为 dict 时,使对象具有不同的行为是可能的,有时也很方便。 ( dict(m) )。'collections.abc ' module .'collections.abc.Mapping 继承您的类或 'collections.abc.MutableMapping向其他用户发出信号,就所有意图和目的而言,您的类是一个映射 * 并且可以预期其行为方式。dict正如您所要求的那样,但可能没有什么理由这样做。因为duck typing ,费心将您的映射对象转换为 dict在大多数情况下,这只是一个额外的不必要步骤。dict -like 类(假设您使用 MutableMapping 而不是只读的 Mapping 基类)。您可以用 dict 做的一切,您可以使用自己的类对象。这可能是,也可能不是,是可取的。numbers 中的数字 abc。模块:int ,从本质上将您的类(class)转变为成熟的int 可能更有意义。所以不需要类型转换。dataclasses module (仅限 Python 3.7),其中包括一个方便的 asdict()效用方法。from dataclasses import dataclass, asdict, field, InitVar
@dataclass
class Wharrgarbl(object):
a: int
b: int
c: int
sum: InitVar[int] # note: InitVar will exclude this from the dict
version: InitVar[str] = "old"
def __post_init__(self, sum, version):
self.sum = 6 # this looks like an OP mistake?
self.version = str(version)
现在你可以这样做: >>> asdict(Wharrgarbl(1,2,3,4,"X"))
{'a': 1, 'b': 2, 'c': 3}
选项 6:typing.TypedDict , 已added in python 3.8 .class Wharrgarbl(TypedDict):
a: str
b: str
c: str
使用此选项,结果对象是 dict (强调:它不是 Wharrgarbl )。根本没有理由将它“转换”到字典中(除非您正在制作副本)。dict ,初始化签名与dict相同因此它只接受关键字参数或其他字典。 >>> w = Wharrgarbl(a=1,b=2,b=3)
>>> w
{'a': 1, 'b': 2, 'c': 3}
>>> type(w)
<class 'dict'>
强调:以上“类”Wharrgarbl实际上根本不是一个新类。它只是用于创建类型化 dict 的语法糖类型检查器具有不同类型字段的对象。dict对象应该具有具有特定值类型的特定键。class MyDict(TypedDict):
def my_fancy_method(self):
return "world changing result"
...但它不会工作:>>> MyDict().my_fancy_method()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'my_fancy_method'
dict的标准“名称” -像鸭子型
关于python - 在python中,如何将类对象转换为dict,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35282222/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack