Title: The Ultimate Guide to The Data Classes in Python 3.7 link to The original author: https://realpython.com/python-data-classes/ Translated by Geir Arne Hjelle
Python3.7’s new dataclass feature greatly simplifies the amount of code required to define class objects. Decorates the design of aclass by using the @dataclass decorator, for example
from dataclasses import dataclass@dataclassclass DataClassCard: rank: str suit: Queen_of_hearts = DataClassCard('Q', 'Hearts')print(queen_of_hearts.rank)print(queen_of_hearts)print(queen_of_hearts == DataClassCard('Q', 'Hearts'))
Copy the code
The results
QDataClassCard(rank='Q', suit='Hearts')True
Copy the code
A regular class, with pre-3.7 syntax, would look something like this
class RegularCard def __init__(self, rank, suit): self.rank = rank self.suit = suit
Copy the code
It doesn’t take much more code, but it’s easy to see that rank and suit are repeated three times in order to initialize, just to initialize an object. In addition, if you try to use the RegularCard class, you will notice that the representation of objects is not very descriptive and that existing classes are not comparable with newly declared classes. Because each declaration uses a new memory address, “==” not only compares the information stored by the class, but also compares whether the memory address is the same.
See the code below for details
queen_of_hearts = RegularCard('Q', 'Hearts')print(queen_of_hearts.rank)print(queen_of_hearts)print(queen_of_hearts == RegularCard('Q', 'Hearts'))
Copy the code
The results
'Q'<__main__.RegularCard object at 0x7fb6eee35d30>False
Copy the code
Dataclass also gives us more useful encapsulation at the bottom. By default, dataclass implements the __repr__ method, which provides a nice string representation; The __eq__ method is also used to do basic object comparisons. If RegularCard wants to implement the above functions, it needs to write a lot of declarations, and the amount of code is scary
class RegularCard(object): def __init__(self, rank, suit): self.rank = rank self.suit = suit def __repr__(self): # class information can be printed out the return (f '{self. The magic __class__. __name__}' f '(rank = {self rank! r}, suit={self.suit! R})') # #conversion character: expected 's', 'r', or 'a' def __eq__(self, other): If other.__class__ is not self.__class__: return NotImplemented return (self.rank, self.suit) == (other.rank, other.suit)
Copy the code
In this tutorial, you’ll learn exactly how convenient the Dataclass class is. In addition to good representations (which can be printed out nicely when using print) and comparisons (whether they are the same), you can see:
-
How to add a default field to a Dataclass object
-
How do I get Dataclass to allow sorting of objects
-
How do I get Dataclass to represent immutable data
-
How do I get Dataclass to handle inheritance
Alternatives to the Dataclass class
You’ve probably seen Nametuple, which is often used to create lightweight data structures that are readable. We can actually create data instances repeatedly with nametuple:
from collections import namedtupleNamedTupleCard = namedtuple('NamedTupleCard', ['rank', 'suit'])
Copy the code
NamedTupleCard can do what DataClassCard can:
queen_of_hearts = NamedTupleCard('Q', 'Hearts')print(queen_of_hearts.rank)print(queen_of_hearts)print(queen_of_hearts == NamedTupleCard('Q', 'Hearts'))
Copy the code
The result is the same as DataClassCard
'Q'NamedTupleCard(rank='Q', suit='Hearts')True
Copy the code
But Nametuple has some limitations and limitations. For example, we cannot change the attribute value of our Nametuple instance because nametuple is fundamentally a tuple class and an immutable data type. In some applications this might be a great feature, but in other applications it would be nice to have more flexibility:
card = NamedTupleCard('7', 'Diamonds')card.rank = '9'
Copy the code
Because nametuple cannot be modified, the following error is reported
AttributeError: can't set attribute
Copy the code
Dataclass basis
Now back to Dataclass, we create a Position class that contains the name and latitude and longitude information:
from dataclasses import dataclass@dataclassclass Position: name: str lon: float lat: Floatpos = Position('Oslo', 10.8, 59.9)print(pos)print(pos. Lat)print(f'{pos. Name} is at {pos.lat}°N, {pos.
Copy the code
Let’s interpret the Position class code. First use @dataclass above Position for decorator syntax.
With the @dataclass decorated Position, we can add some default fields to the Position and declare the type of those fields.
The running results are as follows:
Position(name='Oslo', LON =10.8, LAT =59.9)59.9Oslo is at 59.9°N, 10.8°E
Copy the code
We can also create the Position class using make_dataclass similar to the nametuple syntax. The following code
From dataclasses import make_dataclasspos = make_dataclass('Position', ['name', 'lat', 'lon'])print(pos) <class 'types.Position'>
Copy the code
Dataclass is really just another Python object, except that dataclass wraps __init__(), __repr__(), and __eq__() to make it easier for us to use.
Default property value for the Dataclass class
Adding default values to attribute values is easy in dataclass
From dataclasses import dataclass@dataclassclass Position: name: STR lon: float = 0.0 lat: float = 0.0
Copy the code
The dataclass default setting is similar to the __init__() method
Print (Position('Greenwich', lat=51.8) print(Position('Vancouver', -123.1, 49.3))
Copy the code
The default latitude and longitude is 0. The result is as follows
Position(name='Null Island', LON =0.0, LAT =0.0)Position(name='Greenwich', LON =0.0, LAT =51.8)Position(name='Vancouver', Lon = 123.1, lat = 49.3)
Copy the code
We’ll talk about the Default Factory later, which provides more complex functionality for our default Settings.
Type Hints
You may have noticed that we defined the field with the type hint: name: STR to indicate that the name should be a text string (STR type).
In fact, when you define a field in a data class, you have to add some type hint. If there is no type hint, the field will not be part of the Dataclass class. However, if you don’t want to add explicit types to dataclass classes, use typing.any:
from dataclasses import dataclassfrom typing import Any@dataclassclass WithoutExplicitTypes: name: Any value: Any = 42
Copy the code
Although type hints need to be added in some form when using data classes, these types are not enforced at run time.
withoutexplicittypes = WithoutExplicitTypes(name=38, value='29')print(withoutexplicittypes)
Copy the code
The above code runs without any problems and runs as a result. We find that name is of any type and values are of any type, and while the default is an integer of 42, here we enter a string of 29, which also works.
WithoutExplicitTypes(name=38, value='29')
Copy the code
Add methods
The Dataclass class is a normal Python class, so we can define methods for the Dataclass class just as we define methods for classes.
Here we define the distance calculation method. For the sake of demonstration, we assume that the earth is a two-dimensional plane, and the longitude and latitude represent the position in the coordinate axis. The Euclidean method can be used to calculate the distance.
From dataclasses import dataclass@dataclassclass Position: name: STR lon: float = 0.0lat: Float = 0.0 def distance(self, newpostion): float = 0.0 def distance(self, newpostion): return sqrt((newpostion.lon - self.lon)**2 + (newpostion.lat - self.lat)**2)pos1 = Position('A', 0, Pos3 = Position('C', 3.0, 4.0)print(pos1. Distance (pos2) print(pos1. Distance (pos3))
Copy the code
Point A is the origin, point B (0, 2), and point C (3, 4). The results
2.0 #AB = 25.0 #AC = 5
Copy the code
Flexible dataclass
Now that we’ve looked at the basic features of Dataclass, let’s touch on some of the more advanced uses of Dataclass, such as parameters and the field() function. Combining the two makes it easier to control the classes we create.
Let’s go back to the example of playing cards you saw at the beginning of this tutorial and add a class containing a deck of cards as we work through it:
from dataclasses import dataclassfrom typing import List@dataclassclass PlayingCard: rank: str suit: str@dataclassclass Deck: #Deck: a Deck of cards. The cards parameter is passed into a list that contains multiple instances of the PlayingCard class. cards: List[PlayingCard]queen_of_hearts = PlayingCard('Q', 'Hearts')ace_of_spades = PlayingCard('A', 'Spades')two_cards = Deck([queen_of_hearts, ace_of_spades])print(two_cards)
Copy the code
The two_cards above are the simplest Deck of cards (the Deck class) and run as follows
Deck(cards=[PlayingCard(rank='Q', suit='Hearts'), PlayingCard(rank='A', suit='Spades')])
Copy the code
The articles
100G Python Learning Materials: From Beginner to Master! As a free download
Hundreds of G text data set is waiting for you to claim | free to receive
Enrollment Notice of Hit International Artificial Intelligence Summer School
The 15 best Python libraries for Data Science in 2017
Recommendation system and collaborative filtering, singular value decomposition
Machine learning uses logistic regression to identify numbers in images
PCA dimensionality reduction accelerated model training was applied
Use SkLearn to do natural language processing -1
Use SkLearn to do natural language processing -2
Machine learning | the eight steps to solve the problem 90% of NLP
Symmetry in the Python circuit
The use of date-time libraries in Python
How to extract feature information from text?
Scrapy crawls simple book user information recursively
Meituan business information collection artifact
Use Chardect library to solve the problem of garbled web pages
Results yesterday
Praise, like, forward, AD support are the recognition and support of Big Deng, I hope you can help big Deng forward after reading. Well, only 0.14RMB was collected yesterday!