2016-10-26 34 views
1

假设有一个Person实例personperson可能有一个属性id什么是用一个元素创建一个列表的“pythonic”方法,或者只保留它为空?

我想写让我一个空列表[]当属性为None或丢失或列表[12, ]当属性id为12

def get_id_list(person): 
    try: 
     return [getattr(person, 'id'), ] 
    except AttributeError: 
     return [] 

这完美的作品,但功能是有“pythonic”这样做没有try-except块,也许在一行中?

+3

的try-except块是完全符合Python。仅仅因为某些东西是单行的并不意味着它是实现它的最好方式。 –

+3

在你提供的例子中不需要'getattr',使用'return [person.id]' –

+0

如果Id是13,你想要'[13,]'? – Noelkd

回答

1

你的方法是pythonic,只是做一些调整。

首先,不要在try区块内返回。您可以将id值保留在变量中,并在else子句中正确返回。原因在于你正在执行多个操作,例如获取属性并将其转换为列表(也许更多(在其他情况下)),而你只是捕获AttributeError。而当您使用else时,您可以轻松处理其他异常,而且从编码风格的角度来看它更加优雅。

其次,在这种情况下您不需要使用getattr,您可以直接使用直接属性访问。

而不是使用try-except你可能想检查对象是否有属性,然后返回它的值,但由于请求宽恕比获得许可更容易。校长try-exepct比较好。

def get_id_list(person): 
    try: 
     id = person.id 
    except AttributeError: 
     return [] 
    else: 
     return [id] 
+1

你绝对没有在try块中做回报。感谢提示。 –

+0

当代码非常简单时,为什么在try-clause子句中不返回是很重要的? –

+1

@StevenRumbalski我会说在这种情况下这不是问题,但这是一个很好的习惯。 –

1

您可以使用hasattr()检查属性为:

def get_id_list(person): 
    if hasattr(person, 'id'): 
     return [person.id] # better then getattr(person, 'id') 
    else: 
     return [] 

这可能在一个行可以写成:

def get_id_list(person): 
    return [person.id] if hasattr(person, 'id') else [] 
0

getattr()允许你如果属性是不指定缺省那么你可以使用它,如果你想避免try/catch块。

如果指定的属性不存在,则返回默认值(如果提供),否则引发AttributeError。

id = getattr(person, 'id', None) 

if id is not None: 
    return [id] 
return [] 
+0

如果'hasattr'不存在,这将会有意义,但是如果hasattr(person,'id')else []''更好地表达为'return [person.id]。 –

+0

@StevenRumbalski - 这很可能涉及额外的处理器操作,因为它需要检查同一个字段的存在(访问)两次。更不用说它对人为错误的公开,因为它引入了一个额外的失败点。这是一个有效的方法,就像我的回答是 - 如果不是,那么在允许您指定默认值时不会有任何意义。 – Sayse

1

我会去

def get_id_list(person): 
    _id = getattr(person, 'id', None) 
    return [] if _id is None else [_id] 

然而,这是很好的做法,以确保属性始终定义的,所以你不必使用getattr用默认设置或使用hasattr来检查存在。

0

您可以到getattr()功能提供一个默认值(第三个参数),以如果属性不存在退货:

def get_id_list(person): 
    id_ = getattr(person, 'id', None) 
    return [id_] if id_ is not None else [] 

(这里假设None不是为一个有效的值id根据the Python documentation

+0

如果'hasattr'不存在,这将会有意义,但是如果hasattr(person,'id')else []''更好地表达为'return [person.id]。 –

+1

使用'hasattr'更多的是LBYL方法,通过提供默认值可以实现同样的效果。类似于在字典中使用'.get('foo','default')',而不是首先检查密钥是否存在于第一位。这是相同的原则,但写得更简洁 - 当然提供了我提到的假设(这可能是'id'字段......但取决于用例)。 – plamut

+0

在使用跳跃方法之前,您正在使用一个外观,只是使用错误的功能执行得不好。您使用的默认值不是默认值,而是作为关于对象*是否具有属性*的信号。 –

1

属性):

EAFP: 更容易要求宽恕比权限。这种常见的Python编码风格假定存在有效的键或属性,并且如果假设证明为假,则捕获异常。这种干净而快速的风格的特点是存在很多尝试和除了 陈述。该技术与常见的许多 其他语言LBYL风格如C.

这意味着,你的代码都遵循“官方” Python的方式,检查是否存在属性将Python的少形成鲜明对比。


然而,性能需求可以根据频哪里人对象将不具有id属性最终会覆盖Python的考虑,因为引发异常需要更多的时间不是评估一个简单的条件。

考虑下面的代码:

import os 
from timeit import timeit 


def get_id_list_try(person): 
    try: 
     return [person.id] 
    except AttributeError: 
     return [] 


def get_id_list_if(person): 
    if hasattr(person, 'id'): 
     return [person.id] 
    else: 
     return [] 

class Person(object): 
    def __init__(self, id): 
     self.id = id 

person_with_id = Person(1664) 
person_no_id = object() 

print("try with id: {}".format(
    timeit("get_id_list_try(person_with_id)", number=1000000, 
      setup="from __main__ import get_id_list_try, person_with_id"))) 
print("try no id: {}".format(
    timeit("get_id_list_try(person_no_id)", number=1000000, 
      setup="from __main__ import get_id_list_try, person_no_id"))) 
print("if with id: {}".format(
    timeit("get_id_list_if(person_with_id)", number=1000000, 
      setup="from __main__ import get_id_list_if, person_with_id"))) 
print("if no id: {}".format(
    timeit("get_id_list_if(person_no_id)", number=1000000, 
      setup="from __main__ import get_id_list_if, person_no_id"))) 

它测试的try/catch的性能,使用和不使用的id的if/else方法。它打印此:

try with id: 0.25232274121 
try no id: 2.32747888986 
if with id: 0.364873724104 
if no id: 0.728008592266 

正如你所看到的,try/catch方法有点快,当一个id存在;但是当id不存在时,if/else方法比try/catch方法快3倍。

1

还有的要对此两种基本方式:

EAFP(吨的é asier到一个 SK ˚F orgiveness比P ermission) - 这是你拥有的一切:

def get_id_list(person): 
    try: 
     return [person.id] 
    except AttributeError: 
     return [] 

LBYL(大号 OOK B安伏Ÿ大号 EAP)

def get_id_list(person): 
    if hasattr(person, 'id'): 
     return [person.id] 
    else: 
     return [] 

一般来说,EAFP is "pythonic",但实际上,它取决于你的用例的细节。如果您知道person通常会具有id属性,那么您应该使用EAFP。也就是说,如果是person不是id的例外情况,请使用例外!另一方面,如果person缺少id,则LBYL将更有效。

如果你只是想一个班轮,你可以使用一个conditional expression

return [person.id] if hasattr(person,'id') else [] 
相关问题