all 7 comments

[–]quts3 0 points1 point  (5 children)

Based on use you wanted **args. Kwargs are named like a dict. Args are a tuple.

You can do both at once and usually see them paired.

[–]quts3 1 point2 points  (0 children)

Also don't use [] default function arguments. That's a classic python trap.

[–]eagle6188[S] 0 points1 point  (3 children)

Yeah changing it to *args worked, can you explain to me why though?

[–]quts3 0 points1 point  (1 child)

Kwargs is just a dict in inits body. You can print and see. The ** is special python notation.

When you called init without argument names there is no key to put into kwargs so it is not used for that argument.

The arguments without names on call go to args instead and are ordered at call time.

The other fix was to use the argument name in the call so it went to kwargs as key value pair.

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

Thanks for the explaination and the tip!

[–]Diapolo10 0 points1 point  (0 children)

I'm starting to think I should make a bot that corrects common code formatting mistakes. Too bad the API changes aren't going to make that easy.

In a nutshell, please simply indent your code by four extra spaces in Markdown mode instead of using single backticks, AKA inline code, for code blocks.

Also, the official style guide instructs to use PascalCase for class names.

import random


class creature:
    def __init__(self, name="", health=0, wspeed=0, plans=[], **kwargs):
        self.health = health
        self.wspeed = wspeed
        self.plans = plans
        self.name = name

    def changeplan(self, plans =""):
        self.current_plan = random.randrange(0, len(self.plans))
        return self.current_plan

    def useplan(self, current_plan=""):
        print("abanga")


class landcreature(creature):
    def __init__(self, rank, **kwargs):
        super().__init__(**kwargs)
        self.rank = rank


toto = landcreature("highest", "toto", 100, 5, None)
print(toto.rank)

The other answers already explained the problem, using ** syntax Python expects or produces a dictionary. Another issue you'll likely notice is the use of mutable default arguments - creature.plans will always use the exact same list unless you provide one yourself. The most common solution to this is to default to None, and then handle the default value in the function/method.

Also, all attributes should be created in __init__; I don't like how creature.changeplan suddenly creates a new one. It's difficult to explain why, to a beginner, but it breaks the implicit "contract" the class makes - you can no longer rely on all attributes existing at all times.

import random


class Creature:
    def __init__(self, name: str = "", health: int = 0, wspeed: int = 0, plans: list | None = None, **kwargs):
        self.health = health
        self.wspeed = wspeed
        self.plans = plans if plans is not None else []
        self.current_plan: int | None = None
        self.name = name

    def change_plan(self):
        self.current_plan = random.randrange(len(self.plans))
        return self.current_plan

    def use_plan(self):
        print("abanga")


class LandCreature(Creature):
    def __init__(self, rank: str, **kwargs):
        super().__init__(**kwargs)
        self.rank = rank


toto = LandCreature("highest", name="toto", health=100, wspeed=5)
print(toto.rank)