I have defined the following class-method to define my object from a pandas.DataFrame instead of from a list like so:
class Container(object): @classmethod def from_df(cls, df): rows = [i for _, i in df.iterrows()] return cls(rows)
pylint complains at the
return line with the E1120 'code-smell':
No value for argument 'cls' in constructor call
I can't see anything wrong with it, and it seems to work. Does anybody else maybe have an idea what could be wrong with it?
Update: Ugh, user
rogalski got it (I think): I confused myself by using the same variable name for a class that comes in as argument:
def __init__(self, iterable, cls): self.content = [cls(item) for item in iterable]
I do this because I have different kind of objects coming in and this Container class is the abstract version of this daughter:
class FanContainer(Container): def __init__(self, iterable): super().__init__(iterable, Fan)
Fan being one of several classes that need to be 'contained'.
Rogalski, want to write up an answer along the lines of saying that the error might reference a name of the
__init__ constructor? Cheers! (Now I have to dig why my code isn't stumbling over this...)
Update2 Only realizing know how feeble I have coded this: I am using this basically like so:
fancontainer = FanContainer.from_df(df)
and because I am overwriting the
__init__ in the
FanContainer class, I guess that's why my code still worked? So, the abstract
__init__ is never being called directly, because I never call
Container.from_df(df) but only the daughter classes' classmethods. Guess that can be done prettier a different way.
Typically this error is related to non-complaint function signatures.
Given your code:
class Container(object): def __init__(self, iterable, cls): self.content = [cls(item) for item in iterable] @classmethod def from_df(cls, df): rows = [i for _, i in df.iterrows()] return cls(rows)
from_df scope object to be
Container. Class objects are callables (like functions) and they return new instance of given class. Pylint investigates constructor interface and checks if passed arguments are correct.
In your case passed arguments are incorrect - second required argument (which happens to have same name -
cls - but it exists in different score) is missing. What's why Pylint yields error.
Follow up your edits:
Pylint does not run your code. It statically analyzes it. Since it's possible to call it like
Container.from_df PyLint will warn about possible misuse.
If constructor is never intended to use both arguments outside of your subclasses you may pass default argument and explicitly raise an exception:
class Container(object): def __init__(self, iterable, cls=None): if cls is None: raise NotImplementedError() self.content = [cls(item) for item in iterable] @classmethod def from_df(cls, df): rows = [i for _, i in df.iterrows()] return cls(rows)