Ответ 1
company = country = None
try:
person = Person.find(id=12345)
company = Company.find(person.companyId)
country = Country.find(company.countryId)
except AttributeError:
pass # `person` or `company` might be None
Попытка найти способ очистки некоторых моих кодов.
Итак, у меня есть что-то подобное в моем коде Python:
company = None
country = None
person = Person.find(id=12345)
if person is not None: # found
company = Company.find(person.companyId)
if company is not None:
country = Country.find(company.countryId)
return (person, company, country)
Прочитав учебник по монахам Haskell (в частности, возможно), мне было интересно, можно ли записать его по-другому.
company = country = None
try:
person = Person.find(id=12345)
company = Company.find(person.companyId)
country = Country.find(company.countryId)
except AttributeError:
pass # `person` or `company` might be None
Используйте поведение короткого замыкания и чтобы по умолчанию был настроен пользовательский объект, а None
- false:
person = Person.find(id=12345)
company = person and person.company
country = company and company.country
Python не имеет особо приятного синтаксиса для монад. Если вы хотите ограничить себя использованием чего-то вроде монады Maybe
(подразумевая, что вы сможете использовать Maybe
, вы не сможете создавать общие функции, которые имеют дело с любой монадой), вы можете использовать следующий подход:
class Maybe():
def andThen(self, action): # equivalent to Haskell >>=
if self.__class__ == _Maybe__Nothing:
return Nothing
elif self.__class__ == Just:
return action(self.value)
def followedBy(self, action): # equivalent to Haskell >>
return self.andThen(lambda _: action)
class _Maybe__Nothing(Maybe):
def __repr__(self):
return "Nothing"
Nothing = _Maybe__Nothing()
class Just(Maybe):
def __init__(self, v):
self.value = v
def __repr__(self):
return "Just(%r)" % self.value
Затем сделайте все методы, которые в настоящее время возвращают None
, вместо этого возвращают Just(value)
или Nothing
. Это позволяет вам написать этот код:
Person.find(id=12345).andThen(lambda person: Company.find(person.companyId)).andThen(lambda company: Country.find(company.countryId))
Вы можете, конечно, адаптировать лямбда для хранения промежуточных результатов в переменных; это вам, как это сделать правильно.
Вы проверяли PyMonad?
https://pypi.python.org/pypi/PyMonad/
Он включает в себя не только монаду Maybe, но и монаду списка, классы Functor и Applicative. Моноиды и многое другое.
В вашем случае это будет что-то вроде:
country = Person.find(id=12345) >> (lambda company:
Company.find(person.companyId) >> (lambda country:
Country.find(company.countryId))
Легче понять и чище, чем EAFP.
person = Person.find(id=12345)
company = None if person is None else Company.find(person.companyId)
country = None if company is None else Country.find(company.countryId)
return (person, company, country)
Я думаю, что это идеально подходит для:
Я нахожу getattr
существенным при работе с объектами и атрибутами. Это в значительной степени эквивалентно dict.get(key[, default])
.
person = Person.find(id=12345)
company = person and getattr(person, 'company', None)
country = company and getattr(company, 'country', None)
Больше "Pythonic", чем пытаться реализовать другую парадигму (не то, что это не интересно и круто), было бы добавить интеллект к вашим объектам, чтобы они могли найти свои атрибуты (и независимо от того, существуют они вообще) сами по себе.
Ниже приведен пример базового класса, который использует ваш метод "find" и корреляцию имен атрибутов идентификатора и имен классов для работы с вашим примером. Я ввел минимальные классы Person и Company для поиска компании работа:
class Base(object):
def __getattr__(self, attr):
if hasattr(self, attr + "Id"):
return globals()[attr.title()].find(getattr(self, attr + "Id"))
return None
@classmethod
def find(cls, id):
return "id %d " % id
class Person(Base):
companyId=5
class Company(Base):
pass
И на консоли, после вставки кода выше:
>>> p = Person()
>>> p.company
'id 5 '
С помощью этого Base
ваш код выше может быть просто:
person = Person.find(id=12345)
company = person.company
country = company and company.country