我正在处理来自两个不同网页的数据集,但对于同一个人 - 数据集是合法信息。部分数据在第一页上可用,因此我使用正确的信息初始化被告对象,并将我当前没有数据的属性设置为null
。这是班级:
class Defendant(object):
"""holds data for each individual defendant"""
def __init__(self,full_name,first_name,last_name,type_of_appeal,county,case_number,date_of_filing,
race,sex,dc_number,hair_color,eye_color,height,weight,birth_date,initial_receipt_date,current_facility,current_custody,current_release_date,link_to_page):
self.full_name = full_name
self.first_name = first_name
self.last_name = last_name
self.type_of_appeal = type_of_appeal
self.county = county
self.case_number = case_number
self.date_of_filing = date_of_filing
self.race = 'null'
self.sex = 'null'
self.dc_number = 'null'
self.hair_color = 'null'
self.eye_color = 'null'
self.height = 'null'
self.weight = 'null'
self.birth_date = 'null'
self.initial_receipt_date = 'null'
self.current_facility = 'null'
self.current_custody = 'null'
self.current_release_date = 'null'
self.link_to_page = link_to_page
当我将一个半满的被告对象添加到被告名单中时,这就是它的样子:
list_of_defendants.append(Defendant(name_final,'null','null',type_of_appeal_final,county_parsed_final,case_number,date_of_filing,'null','null','null','null','null','null','null','null','null','null','null','null',link_to_page))
然后,当我从其他页面获取其余数据时,我将这些属性设置为null,如下所示:
for defendant in list_of_defendants:
defendant.sex = location_of_sex_on_page
defendant.first_name = location_of_first_name_on_page
## Etc.
我的问题是:当我只有一半的信息需要存储在其中时,是否有更多的pythonic方法可以为类添加属性或者更简单的初始化类对象的方式?
答案 0 :(得分:4)
首先,对您设置为null的任何参数使用默认值。这样,您甚至不需要在实例化对象时指定这些参数(并且您可以使用参数名称以任何顺序指定任何您需要的参数)。除非使用字符串有某些特定原因,否则应使用Python值None
而不是字符串"null"
。在Python 2.x中,具有默认值的参数需要最后一个,因此link_to_page
需要在这些参数之前移动。
然后,您可以通过更新实例的__dict__
属性来设置属性,该属性存储附加到实例的属性。每个参数都将设置为具有相同名称的实例的属性。
def __init__(self, full_name, first_name, last_name, type_of_appeal, county, case_number,
date_of_filing, link_to_page, race=None, sex=None, dc_number=None,
hair_color=None, eye_color=None, height=None, weight=None, birth_date=None,
initial_receipt_date=None, current_facility=None, current_custody=None,
current_release_date=None):
# set all arguments as attributes of this instance
code = self.__init__.__func__.func_code
argnames = code.co_varnames[1:code.co_argcount]
locs = locals()
self.__dict__.update((name, locs[name]) for name in argnames)
您也可以考虑从其他两个名称参数中合成full_name
。然后,您不必传递冗余信息,它永远不会匹配。您可以通过酒店动态执行此操作:
@property
def full_name(self):
return self.first_name + " " + self.last_name
为了更新,我会添加一个方法来执行此操作,但使用**
接受仅关键字参数。为了帮助保护数据的完整性,我们将仅更改已存在且设置为None
的属性。
def update(self, **kwargs):
self.__dict__.update((k, kwargs[k]) for k in kwargs
if self.__dict__.get(k, False) is None)
然后,您可以通过一次通话轻松更新所需的所有内容:
defendant.update(eye_color="Brown", hair_color="Black", sex="Male")
要确保实例已完全填写,您可以添加一个检查的方法或属性,以确保所有属性都不是None
:
@property
def valid(self):
return all(self.__dict__[k] is not None for k in self.__dict__)
答案 1 :(得分:2)
如果您可以将每个属性作为名称 - 值对传递,则可以使用以下内容:
class Defendant(object):
fields = ['full_name', 'first_name', 'last_name', 'type_of_appeal',
'county', 'case_number', 'date_of_filing', 'race', 'sex',
'dc_number', 'hair_color', 'eye_color', 'height', 'weight',
'birth_date', 'initial_receipt_date', 'current_facility',
'current_custody', 'current_release_date', 'link_to_page']
def __init__(self, **kwargs):
self.update(**kwargs)
def update(self, **kwargs):
self.__dict__.update(kwargs)
def blank_fields(self):
return [field for field in self.fields if field not in self.__dict__]
def verify(self):
blanks = self.blank_fields()
if blanks:
print 'The fields {} have not been set.'.format(', '.join(blanks))
return False
return True
用法看起来像:
defendant = Defendant(full_name='John Doe', first_name='John', last_name='Doe')
defendant.update(county='Here', height='5-11', birth_date='1000 BC')
defendant.verify()
# The fields type_of_appeal, case_number, date_of_filing, race... have not been set.
将其扩展为使用必填字段和可选字段非常简单。或者,您可以为初始化添加必需的参数。或者,您可以检查以确保每个名称 - 值对都具有有效名称。等等...
答案 2 :(得分:1)
所以,一个更简单的例子来说明你可以做什么:
class Foo:
def __init__(self, a, b, e, c=None, d=None):
self.a = a
self.b = b
self.c = c
self.d = d
self.e = e
但是,如果您从不拥有c
和d
,当您需要实例化时,我建议您这样做:
class Foo:
def __init__(self, a, b, e):
self.a = a
self.b = b
self.c = None
self.d = None
self.e = e
编辑:另一种方法可能是:
class Defendant(object):
__attrs = (
'full_name',
'first_name',
'last_name',
'type_of_appeal',
'county',
'case_number',
'date_of_filing',
'race',
'sex',
'dc_number',
'hair_color',
'eye_color',
'height',
'weight',
'birth_date',
'initial_receipt_date',
'current_facility',
'current_custody',
'current_release_date',
'link_to_page'
)
def __update(self, *args, **kwargs):
self.__dict__.update(dict(zip(self.__attrs, args)))
self.__dict__.update(kwargs)
def __init__(self, *args, **kwargs):
self.__dict__ = dict.fromkeys(Defendant.__attrs, None)
self.__update(*args, **kwargs)
update_from_data = __update
if __name__ == '__main__':
test = Defendant('foo bar', 'foo', 'bar', height=180, weight=85)
test.update_from_data('Superman', 'Clark', 'Kent', hair_color='red', county='SmallVille')
答案 3 :(得分:1)
我会说最pythonic的方式是这样的:
Model
清洁,一切都只定义一次并自动运行。
关于那个Defendant
超类......如果你正在使用像Django这样的任何网络框架,那么从他们的模型继承,你就完成了。它具有您需要的所有接线。
否则,实现简短而甜蜜的简单方法,继承您的class Model(object):
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
课程:
d1 = Defendant(height=1.75)
print d1.height
d2 = Defendant(full_name='Peter')
print d2.full_name
根据您可用的字段进行实例化:
__init__
你可以通过一些元编程实现更酷的东西,比如字段类型检查,值检查,重复声明等等。如果你使用的是python 3,你可以轻松地将值传递给{{1方法由args(基于声明的顺序)或kwargs。