(对不起。标题很不清楚。我想不出一个好的。)
说我有一个这样的网址(它是root-relative):
"/forums/support/windows/help_i_deleted_sys32/6/"
我试图把它分成这样的类结构:
class Forum_Spot:
def __init__(self, url):
parts = url.strip("/").split("/")
#parts is now ["forums", "support", "windows", "help...", "6"]
self.root = "forums"
self.section = "support"
self.subsection = "windows"
self.thread = "help..."
self.post = "6"
但是说我不知道网址到底有多长(可能是“/ forums / support /”,“/ forums / support / windows /”等)(但我知道它不会是任何深度超过5级)。任何人都可以想出一种优雅的方式来分配这些值,让任何未分配的部分都是None
吗? (即“/ forums / support / windows /”,线程和帖子属性为None)
我知道我可以这样做:
class Forum_Spot:
def __init__(self, url):
parts = url.strip("/").split("/")
#parts is now ["forums", "support", "windows", "help...", "6"]
if len(parts) > 0:
self.root = parts[0]
else:
self.root = None
if len(parts) > 1:
self.section = parts[1]
else:
#etc
但这显然是超级优雅和令人讨厌的劳动密集型。任何人都可以想到更优雅的解决方案,保持班级签名相同吗? (我可以转换__init__
函数来获取关键字参数,默认为None
,但我希望能够直接传入URL并让类自己解决这个问题)< / p>
谢谢!
答案 0 :(得分:7)
使用序列解包:
>>> strs = "/forums/support/"
>>> spl =strs.strip('/').split('/')
>>> a,b,c,d,e = spl + [None]*(5-len(spl))
>>> a,b,c,d,e
('forums', 'support', None, None, None)
>>> strs = "/forums/support/windows/"
>>> spl =strs.strip('/').split('/')
>>> a,b,c,d,e = spl + [None]*(5-len(spl))
>>> a,b,c,d,e
('forums', 'support', 'windows', None, None)
>>> strs = "/forums/support/windows/help_i_deleted_sys32/6/"
>>> spl =strs.strip('/').split('/')
>>> a,b,c,d,e = spl + [None]*(5-len(spl))
>>> a,b,c,d,e
('forums', 'support', 'windows', 'help_i_deleted_sys32', '6')
答案 1 :(得分:3)
您可以在类中添加一个设置适当默认值的setter方法:
class Forum_Spot:
def __init__(self, url):
parts = url.split('/')[1:]
# use function argument unpacking:
self.set_url(*parts)
def set_url(self, root, section=None, subsection=None, thread=None, post=None):
self.root = root
self.section = section
self.subsection = subsection
self.thread = thread
self.post = post
答案 2 :(得分:3)
我建议使用itertools.izip_longest
(在Python 3中重命名为zip_longest
)通过创建name, value
元组来构建字典,并为None
填写任何缺失值:< / p>
import itertools
names = ["root", "section", "subsection", "thread", "post"]
values = url.strip("/").split("/")
name_value_dict = dict(itertools.izip_longest(names, values))
现在您可以直接使用字典,如果需要在对象上创建成员变量,可以使用dict.update
将其合并到现有字典中:
self.__dict__.update(name_value_dict)
答案 3 :(得分:1)
比moooeeeep更好的方法是使用namedtuple
。 (或者更确切地说,是具有默认值的子类。)
from collections import namedtuple
class _Path(namedtuple('Path', 'root section subsection thread post')):
def __new__(cls, root=None, section=None, subsection=None, thread=None, post=None):
# add default values
return super(_Path, cls).__new__(cls, root, section, subsection, thread, post)
Path = lambda s: _Path(*s.strip('/').split('/'))
然后......
>>> Path("/forums/support/")
_Path(root='forums', section='support', subsection=None, thread=None, post=None)