Reputation: 23
Here is a screenshot from a lecture that I am going through at school:
My question is, if the class data fields are already being defined:
slices=16
temperature=75.0
Do those values (16 and 75.0) also need to be passed to the __init__
method or can you just pass the variables names, because they are already assigned to those values?
Not sure why/if you would need to pass the default values when they are the exact same as what the variables are already set to? so instead of:
def __init__(self, slices=16, temperature=75.0)
Could you just do:
def __init__(self, slices, temperature)
Updated new question If you removed the initial class-level variables at the top, and are only defining them in the constructor class, are they only scoped to the constructor class? Or are they available throughout the entire class, even though you didn't define them at the very top (class-level)?? Example:
Class Pizza(object):
# no class-level slice or temp variables
def __init__(self, slices=16, temperature=75.0):
self.slices = slices
self.temperature = temperature
Or, because you are defining them as "self.slices", they are by default passed to all of the other methods when you pass (self) into the other methods?
Upvotes: 0
Views: 914
Reputation: 155546
The class defined in your lecture is dumb (not very dumb, just pointless and misleading, as you've clearly been misled by it). There is zero reason to define class attributes that happen to share the same value as the default arguments to the initializer. The only thing doing that accomplishes is:
Pizza.slices
and Pizza.temperature
and see that the abstract concept of a pizza (not a specific pizza) somehow has a known number of slices and a known temperature, anddel mypizza.slices
, then future access to mypizza.slices
will still "work", but will retrieve the value from the class attribute (since the instance attribute was blown away). Sane code should almost never do this.In all other ways, there is no relationship between the class level attributes and the defaults defined for the __init__
initializer method; the moment __init__
assigns to self.slices
and self.temperature
, it shadows the class level attributes so they cannot be directly accessed from that instance of the class (without deleting the instance attributes or bypassing the instance to look at the values on the class itself).
So no, you can't do:
def __init__(self, slices, temperature):
self.slices = slices
self.temperatue = temperature
because the arguments named slices
and temperature
have nothing to do with the class attributes. By removing their defaults, the user of your class is forced to provide their own values, and there is no default that will be provided (they could, I suppose, do Pizza(Pizza.slices, Pizza.temperature)
, but that's an insane way to handle defaults).
To your updated question, even without the class variables,
class Pizza:
# no class-level slice or temp variables
def __init__(self, slices=16, temperature=75.0):
self.slices = slices
self.temperature = temperature
works just fine. Outside of any methods of the class, slices
and temperature
won't exist, but any other methods you define on Pizza
will be able to access that instance's slice
and temperature
attributes by looking them up on self
, just like __init__
did when it assigned to them (with self.slices
or self.temperature
), and anyone who creates an instance of Pizza
, say, with mypizza = Pizza(12, 140)
, can do mypizza.slices
to see the attribute for the instance they hold.
A note on the class attributes: In normal cases, they're stupid and nonsensical. There is an exception for dataclasses though, where you define them at class level for the express purpose of helping the dataclasses
module dynamically generate your code, removing the need to write a __init__
with separate defaults entirely. For example:
from dataclasses import dataclass
@dataclass
class Pizza:
slices: int = 16
temperature: float = 75.0
is a perfectly reasonable way to write the baseline class, and it uses those annotations and defaulted assignments to generate as __init__
for you (along with reasonable default implementations of __repr__
and __eq__
, and other special methods if you pass specific arguments to the @dataclass
decorator, saving you a ton of boilerplate required for minimal expected class functionality). It does leave the class attributes in place, which is arguably a bad idea, but at least you're getting something useful out of the deal, it's not just repeating the same defaults in two essentially unrelated places, one of which is completely useless.
Upvotes: 0
Reputation: 36621
If you use:
def __init__(self, slices, temperature)
Then slices
and temperature
are parameters that must be specified.
What you can do is create a variable, and then use that as the default for the function parameter.
a = "foo"
def b(c=a):
print(c)
Just keep in mind that if you redefine that variable, it does not affect the default value for the function.
>>> a = "foo"
>>> def b(c=a):
... print(c)
...
>>> b()
foo
>>> a = 42
>>> b()
foo
Upvotes: 0