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)
and 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)
with 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)
Pylint resolves cls
in 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. That'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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With