简体   繁体   English

Python 等价于 Scala 案例类

[英]Python equivalent of Scala case class

Is there any Python equivalent of Scala's Case Class?是否有任何 Python 等价于 Scala 的 Case Class? Like automatically generating constructors that assign to fields without writing out boilerplate.就像自动生成分配给字段的构造函数一样,而无需写出样板。

The current, modern way to do this (as of Python 3.7) is with a data class .当前的现代方法(从 Python 3.7 开始)是使用数据类 For example, the Scala case class Point(x: Int, y: Int) becomes:例如,Scala case class Point(x: Int, y: Int)变为:

from dataclasses import dataclass

@dataclass(frozen=True)
class Point:
    x: int
    y: int

The frozen=True part is optional; frozen=True部分是可选的; you can omit it to get a mutable data class.您可以省略它以获得可变数据类。 I've included it for parity with Scala's case class.我已经将它包含在 Scala 的 case 类中。

Before Python 3.7, there's collections.namedtuple :在 Python 3.7 之前,有collections.namedtuple

from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])

Namedtuples are immutable, as they are tuples.命名元组是不可变的,因为它们是元组。 If you want to add methods, you can extend the namedtuple:如果要添加方法,可以扩展命名元组:

class Point(namedtuple('Point', ['x', 'y'])):
    def foo():
        pass

If you use python3.7 you get data classes as @dataclass .如果您使用python3.7您将获得数据类为@dataclass Official doc here - 30.6.官方文档在这里 - 30.6。 dataclasses — Data Classes dataclasses — 数据类

from dataclasses import dataclass

@dataclass
class CustomerOrder:
  order_id: int
  customer_id: str
  item_name: str

order = CustomerOrder(1, '001', 'Guitar')
print(order)

Make sure to upgrade python3 to python 3.7 or if you use python 3.6 install dataclass from pypi确保将 python3 升级到 python 3.7 或者如果你使用 python 3.6 从pypi安装数据类

In macos: brew upgrade python3在 macos 中: brew upgrade python3

While above data class in scala looks like,虽然上面的scala数据类看起来像,

scala> final case class CustomerOrder(id: Int, customerID: String, itemName: String)
defined class CustomerOrder

The other answers about dataclass are great, but it's worth also mentioning that:关于dataclass的其他答案很棒,但还值得一提的是:

  • If you don't include frozen=True , then your data class won't be hashable.如果您不包括frozen=True ,那么您的数据类将不可散列。 So if you want parity with Scala case classes (which automatically define toString , hashcode and equals ) then to get hashcode , you will need @dataclass(frozen=True)因此,如果您希望与 Scala 案例类(自动定义toStringhashcodeequals )相同,那么要获取hashcode ,您将需要@dataclass(frozen=True)
  • even if you do use frozen=True , if your dataclass contains an unhashable member (like a list), then the dataclass won't be hashable.即使您确实使用了 freeze frozen=True ,如果您的数据类包含不可散列的成员(如列表),那么该数据类也不会是可散列的。
  • hash(some_data_class_instance) will be equal if the values are equal (and frozen=True )如果值相等(并且hash(some_data_class_instance) frozen=True ), hash(some_data_class_instance)将相等
  • From a quick empirical test, equality comparisons don't appear to be any faster if your type is hashable.从快速的经验测试来看,如果您的类型是可散列的,则相等比较似乎不会更快。 Python is walking the class members to compare equality. Python 正在带领班级成员比较相等性。 So even if your frozen dataclass has all hashable members (eg tuples instead of lists), it will still walk the values to compare equality and be very slow.因此,即使您的frozen数据类具有所有可散列成员(例如元组而不是列表),它仍然会遍历值以比较相等性并且非常慢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM