Python:** kargs而不是重载?

时间:2010-07-05 12:32:54

标签: python design-patterns overloading

我有一个概念性的Python设计困境。

假设我有一个City类,它代表数据库中的一个城市。 City对象可以通过两种方式初始化:

  1. 整数(实际上是数据库中现有城市的ID)
  2. 属性列表(namecountrypopulation,...),它们将在数据库中生成新城市并检索其ID。
  3. 这意味着City对象将始终具有ID - 初始化ID或从数据库派生的新创建ID。

    经典的Java方法overload the constructor - 一个构造函数将获得一个int参数,另一个将获得许多强类型参数。

    我没能在Python中找到一种优雅的方法:

    • 我可以使用单个方法get_city_id创建基类,并派生CityFromID和。{ CityFromNewData来自它,但要努力解决这种语言缺陷。
    • 使用类方法seems awkward
    • 使用带有长参数列表的构造函数也很尴尬:我将两个城市ID和替代品放在一起,并在方法中验证只有特定子集具有值。

    使用**kargs似乎非常不优雅,因为构造函数的签名没有明确说明所需的输入参数,而文档字符串是不够的:

    class City(object):
        def __init__(self, city_id=None, *args, **kargs):
            try:
                if city_id==None:
                    self.city_id=city_id
                else:
                    self.city_name=kargs['name']
            except:
                error="A city object must be instanciated with a city id or with"+\
                " full city details."
                raise NameError(error)
    

    构造函数重载是否有Pythonic,优雅的解决方案?

    亚当

3 个答案:

答案 0 :(得分:7)

怎么样:

class City(object):
   def __init__(self, name, description, country, populations):
      self.city_name = name
      # etc.

   @classmethod
   def from_id(cls, city_id):
       # initialise from DB 

然后你可以做普通的对象创建:

 >>> c = City('Hollowberg', '', 'Densin', 3)
 >>> c.id
 1233L

 >>> c2 = City.from_id(1233)

~~~~~~

另外,您可能需要查看SQLAlchemy(以及Elixir)以获得更好的方法来执行这些操作

答案 1 :(得分:4)

有一种名为Data Access Object的设计模式通常用于您的案例中。根据它,您应该在两个类City和CityDAO中分离数据对象的获取和创建:

class City:

    def __init__(self, name, country):
        self.name = name
        self.country = country 


class CityDAO:

    def fetch(self, id):
        return query(...)

    def insert(self, city):
        query(...)

答案 2 :(得分:2)

我认为类(工厂)方法是最好的方法,因为方法名称已经明确说明了所做的事情。两个独立的功能也可以:

def load_existing_city(id):
    ...
def create_new_city(name, population, ...):
    ...