I would love to suggest fairly popular in JS world feature for Object Destructuring.
Usually it is implemented like
const person = {
name: "John Doe",
age: 31
}
const {name, age} = person;
// now we can reference name or age like
// const name = person.name
Python has similar syntax for lists and tuples. There is also itemgetter but it is kinda ugly.
Ideally it should work like this:
class Person:
name: str
age: int
# constructor omitted for brevity
person = Person(name="John Doe", age=31)
# here we perform destructuring
# because interpreter already knows that person is an instance of a class it takes name as literal and can do something like getattr(person, 'name', None) under the hood
name, age = person
print(name, age)
This approach can be 100% compatible with tuples and lists.
Also it would make named tuples destructuring absolute breeze because it can rely on name instead of positional argument.
from dataclasses import dataclass, astuple
@dataclass
class Person:
name: str
age: int
person = Person(name="John Doe", age=31)
name, age = astuple(person)
print(name, age)
This is something I would love, but I much prefer Rust’s syntax over JavaScript’s (notice how Rust’s version has the object name on the left-hand side):
struct Person {
name: String,
age: u8,
}
let person = Person { name: "John Doe".to_string(), age: 31 };
let Person { name: name, age: age } = person;
println!("{name}: {age}");
@dataclass
class Person:
name: str
age: int
person = Person(name="John Doe", age=31)
Person(name=name, age=age) = person
print("{name}: {age}")
from dataclasses import dataclass
@dataclass
class Person:
name: str
age: int
def __iter__(self):
# iterate through all fields in the order declared
for field in self.__dataclass_fields__:
yield getattr(self, field)
person = Person("John Doe", 31)
name, age = person
print(name, age) # John Doe 31
Rust syntax is explicit but bloated. This is exactly what I want to avoid.
Good syntax is concise, easy to interpret and intuitive.
attr_a, attr_b = some_object
Is easy to write, easy to understand, it is compact and already exists.
If we do a simple expansion to dicts and objects this will make code leaner.
The programming languages exist to make work of engineers easier. All of them take different routes and trying to address various concerns.
Rust designed to build system software, software that built to run forever. Hence, it must have explicit syntax to avoid memory leaks and accidental memory corruption. It is complicated for a purpose.
Python is designed to write a simple code that easy to interpret once you know a few basic constructs. This is why it has garbage collection and all relevant consequences. And this is a reason to keep the language lean.
I think that some new way of object destruction would make sense, but it should not only work for named tuples and dataclasses, but also for dicts. This, however, makes the following syntax unsuitable:
because we can already write a, b = {'b':1, 'a':2}, which sets a=1 and b=2.
name = attorney.mother_in_law.husband.mother.name
age = attorney.mother_in_law.husband.mother.age
husband = attorney.mother_in_law.husband.mother.husband
# the list goes on
or even with some extra step it is still scales poorly:
mother = attorney.mother_in_law.husband.mother
name = mother.name
age = mother.age
# ..and it continues to be repetitive
Good engineers aren’t paid by number of lines. And it is our choice to select what type of engineers we want to be.
My teacher always said that good engineers are lazy engineers. They don’t like repetitive work, they don’t do anything twice.
I am not trying to cajole anyone into my way of thinking. I am trying to simply show that some ways are easier when we apply ourselves to learn them.