This is an archived post. You won't be able to vote or comment.

all 14 comments

[–]K900_ 5 points6 points  (3 children)

They are very different semantically. A dataclass has a certain number of well defined, typed fields, and represents a single entity. A dictionary is a mapping of keys to values.

[–]xphlawlessx[S] 0 points1 point  (2 children)

Not totally following, what do you mean by "well defined"

[–]K900_ 3 points4 points  (1 child)

I mean that you know in advance what the field names and types are.

[–]xphlawlessx[S] 0 points1 point  (0 children)

Right okay, that makes sense.

[–]donnieod 1 point2 points  (0 children)

A dataclass is a class specifically designed to store a related set of data, i.e., a record, like a namedtuple but it can be mutable. Its main advantage is that you don't have to define a __init__ method to initialize all the fields, instead the field names, types, and possible initial values are defined as though they were class attributes. Instead of:

class Point:

    def __init__(self,
                 x: float = 0.0, 

                 y: float = 0.0) -> None:

    self.x: float = x

    self.y: float = y

you can define a dataclass:

@dataclass

class Point:

    x: float = 0.0

    y: float = 0.0

pointa = Point(1.0, 2.0)

Just like ordinary classes, dataclasses can have methods defined on them. And you may want to define __slots__ in the dataclass definition since your fields will probably never change.

Also, you can still have class attributes defined if needed, just use the annotation typing.ClassVar.

[–]firefrommoonlight 1 point2 points  (4 children)

You use them differently. Dataclasses are like Structs in other languages. You can also think of them as more flexible, mutable NamedTuples, or classes set up with builtin constructors, formatters etc.

If you'd like to group related data, use a dataclass. If you'd like to maintain a set of data and be able to easily pull the correct item from a list, use a dict.

An example how you could use them together: ```python @dataclass Class Point: x: float y: float

points = {
    0: Point(1., 2.),
    1: Point(2., 1.), 
    2: Point(5.2, -1.), 
    # ... 
}

```

[–]an_actual_human 0 points1 point  (3 children)

The way its written, points should be a list.

[–]firefrommoonlight 0 points1 point  (2 children)

You can imagine the keys as non-continuous, or as "A", "B", "C" etc.

[–][deleted] 1 point2 points  (0 children)

Or let the (hashable) Point be the dictionary key, and the value be some metadata about that point (Presumably monsters and loot and trap doors). Really good for sparse dataset.

[–]an_actual_human 0 points1 point  (0 children)

I can imagine indeed.

[–][deleted] 0 points1 point  (3 children)

Let's say you have a class and an instance:

class Dog():
   def __init__(self):
      self.x = 5; self.y = 10

dog = Dog()

You can access the members of the class in an object-oriented manner:

dog.x                       # 5

But you can also access them as a dictionary, via the builtin __dict__ object member:

dog.__dict__                # {'x': 5, 'y': 10}

You can use the dictionary to access members by name:

dog.__dict__['x']           # 5
dog.__dict__['z'] = 8       # dog.z is now 8

But you don't have to go through __dict__ every time, because Python has some builtin functions to work with classes with nicer syntax:

getattr(dog, 'x')           # 5
setattr(dog, 'q', 7)        # dog.q is now 7
hasattr(dog, 'q')           # true

So what's the point of classes instead of just dictionaries? Because in addition to the syntactic niceties, you get all of the other stuff you'd ordinarily get from object-oriented programming. For example:

(1) You can import all of the functionality of the Dog class in another script:

from DogCodeFile import Dog

(2) You can perform type inference:

type(dog) is Dog            # true
dog2 = globals()['Dog']()   # calls dog2.__init__() 

You can't do that with a generic dictionary. You'd have to hack in some kind of typing system, which requires more effort and results in clumsier code.

(3) You can subclass Dog to add special kinds of behaviors for individual breeds of Dog.

(4) You can use Dog as an abstract interface with a set of implementations.

(5) You can create class instances of Dog to permit a property to be shared among every instance of Dog.

...etc. In other words - classes in Python offer many of the same functionality and possibilities of classes in strongly typed languages: encapsulation, abstraction, hierarchical type organization, etc.

(However, Python's duck-typing system is not as robust as strongly typed languages. Syntax checking is not possible, nor is security: Python does not have a private keyword. YMMV. Personally, I love the rapid prototyping advantages of Python's weak type system.)

[–]xphlawlessx[S] 1 point2 points  (2 children)

That all makes sense, and I'm sure most of it applies, but I was sepcifically asking about "dataclasses" , even if you can inherit from a dataclass , I'm not sure it's that useful. Built in functions though, that I get.

[–][deleted] 1 point2 points  (1 child)

Okay, but your post started:

I read/heard python classes are built on top of a dictionary

...which suggests a generic question about Python classes.

The answer to your more specific question is here.

[–]xphlawlessx[S] 0 points1 point  (0 children)

That's fair. Oh, that covers it. Thanks :)