Python Forum

Full Version: "unexpected keyword arg" when initializing my subclasses
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi,

i get confused when i build my class stuctures. I got 2 questions.

1.
Since all of my classes will use the some base attributes i collected them in a base class.
When i call my constructor for k1 , I get
"unexpected keyword arg" error for the attribute "material" - which is derived from its base class.
How to avoid this?

2.
i am not sure if my style is pytonic the way as below.
Normally i have many more attributes (~up to 20) in each class. Maybe there is a better method.

class MyClass1(MyBaseClass):
    def __init__(self,
                 name=None,
                 length=None,
                 height=None,
                 color=None,
                 ) -> None:

        super().__init__() 

        self.__name = name
        self.__length = length
        self.__height = height
        self.__color = color
 

class MyClass2(MyBaseClass):
    def __init__(self,
                 name=None,
                 vol=None,
                 weight=None,
                 dense=None,
                 ) -> None:

        super().__init__() 

        self.__name = name
        self.__vol = vol
        self.__weight = weight
        self.__dense = dense                      

                       

class MyBaseClass(metaclass=ABCMeta):

    def __init__(self,
                 material=None,
                 origin=None,
                 manufacturer=None,
                 ) -> None:

        self.__material = material
        self.__origin = origin
        self.__manufacturer = manufacturer

                       

k1 = MyClass1(name=get_name(input_data),
			  length=get_length(input_data),
			  height=get_height(input_data),
			  color=get_color(input_data),
			  material=get_basis_info_material(input_data),
			  origin=get_basis_info_origin(input_data),
			  manufacturer=get_basis_info_manufacturer(input_data),
            )
When you call the constructor MyClass1(), you can pass only the arguments that are defined in the signature of the MyClass1.__init__() method. That's why you have the unexpected keyword arg error.

If these are the first python classes that you write, keep it as simple as possible, avoid ABCMeta and private attributes, you are only adding complexity with these.
Yes, first classes. But why you assume it will adding complexity? What is the alternative?

IMHO when using common attributes (and methods), why I shouldn't inherit from that Base-Class?
This way it looks clean and structured (at least to me).

But i am not such expert though :-)
(Nov-25-2022, 07:12 PM)Phaze90 Wrote: [ -> ]why I shouldn't inherit from that Base-Class?
Metaclasses are for metaprogramming. You don't need that for your first class, so remove the metaclass.

Private attributes with double underscores are more an annoyance than anything else. In Python there is no compiler to enforce more or less privacy on members, so privacy is usually a gentlemen's agreement between the programmer and his/her colleagues. To indicate that an attribute is not in the object's public interface, use a single underscore.

You could write the code this way for example

class MyBaseClass:

    def __init__(self,
                 material=None,
                 origin=None,
                 manufacturer=None,
                 ) -> None:

        self._material = material
        self._origin = origin
        self._manufacturer = manufacturer

class MyClass1(MyBaseClass):
    def __init__(self,
                 name=None,
                 length=None,
                 height=None,
                 color=None,
                 **kwargs,
                 ) -> None:

        super().__init__(**kwargs)

        self._name = name
        self._length = length
        self._height = height
        self._color = color


class MyClass2(MyBaseClass):
    def __init__(self,
                 name=None,
                 vol=None,
                 weight=None,
                 dense=None,
                 **kwargs,
                 ) -> None:

        super().__init__(**kwargs)

        self._name = name
        self._vol = vol
        self._weight = weight
        self._dense = dense

k1 = MyClass1(name='name',
              length='leng',
              height='heig',
              color='colo',
              material='mate',
              origin='orig',
              manufacturer='manu',
            )
print(k1)
print(vars(k1))
Output:
<__main__.MyClass1 object at 0x7fd271dd3ee0> {'_material': 'mate', '_origin': 'orig', '_manufacturer': 'manu', '_name': 'name', '_length': 'leng', '_height': 'heig', '_color': 'colo'}