0

I have a very basic question about why I need __init__ in declaring a class in Python.

For example, in this link, an example was introduced

class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age

p1 = Person("John", 36)

print(p1.name)
print(p1.age) 

But the above example requires a series of arguments as ("John", 36). When the number of arguments is large, they may be error-prone in the input. I can use *args, but it also requires the order of argument. If I just provide a default value of the name and age, and modify in need, will it simplify the practice? For example

class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age
    
class Person2:
  name = "John"
  age = 36    
  
class Person3:
  def __init__(self, *args):
    self.name = args[0]
    self.age = args[1]
      

p1 = Person("John", 36)
print(p1.name)
print(p1.age)

p2 = Person2()
print(p2.name)
print(p2.age)


p2.name = "Mike"
p2.age = 35
print(p2.name)
print(p2.age)


p3 = Person3("John", 36)
print(p3.name)
print(p3.age)

Person2 is perhaps the simplest. But, will Person2 be a good practice?

7
  • For data "structs", look into dataclass from the dataclasses package from the standard library. If you plan for more complex functionality you should stick with a conventional implementation that includes named arguments and an __init__ (in other words, don't ever do Person3). Commented Dec 11, 2022 at 0:17
  • 2
    What you propose in the question isn't actually any less error-prone. It just means you silently get the wrong attribute values if you screw up, instead of getting an error message. Error messages are better than silent failures. They let you know about the problem and help you fix it. Commented Dec 11, 2022 at 0:22
  • When the number of arguments is large, it probably means you should define some more types: Foo(Bar(a, b), Baz(c, d) instead of Foo(a, b, c, d), for example. Commented Dec 11, 2022 at 1:00
  • @chepner do you mean nested class? Commented Dec 11, 2022 at 1:19
  • 1
    Composition just means using types in other types. It's unlikely that all the arguments need to be passed directly to Foo. For example, you can define a line with 2 points, where each point has an x- and a y-coordinate. Instead of Line(x1, y1, x2, y2), define a Point class to represent the points and have Line take two instances of Point as arguments, not 4 numbers: `Line(Point(x1, y1), Point(x2, y2)). There's less room for error when any given value requires fewer arguments to define. Commented Dec 11, 2022 at 1:38

1 Answer 1

1

You may want to read into the difference of class and an instance of a class: Person2 will not fly as every person would be the same. You use the class here basically as a namespace without further usage.

Person3 is basically a bad version of Person1.

Person1 will be ok and not error prone as you can also pass the arguments as keyword arguments (Person(name=..., age=...).

You may also have a look at dataclasses as they remove this kind of boilerplate: https://docs.python.org/3/library/dataclasses.html

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.