__init__ (constructor) question when inheriting

Please post any questions about developing your plugin here. Please use the search function before posting!
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

__init__ (constructor) question when inheriting

Postby BackRaw » Sun Jun 21, 2015 11:22 pm

Hi,

do I have to implement __init__ in a subclass if the parameters are the same for the superclass? Like so:

Syntax: Select all

class SuperClass(object):

def __init__(self, param1):
self.param1 = param1


class SubClass(SuperClass):

# is this needed here? -- param1 is the same for SubClass and SuperClass
def __init__(self, param1):
super(SubClass, self).__init__(param1)

def new_method(self):
self.param1.method1()
If not, would this be sufficient?

Syntax: Select all

class SuperClass(object):

def __init__(self, param1):
self.param1 = param1


class SubClass(SuperClass):

def new_method(self):
self.param1.method1()
I'm asking because I want to make my code more readable and I want to cut out things which are not needed.

Edit: What about subclassing dicts and other python builtins? Does python 'know' if the object is a dict if I skip calling the constructor? :)
My Github repositories:

Source.Python: https://github.com/backraw
User avatar
satoon101
Project Leader
Posts: 2703
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Mon Jun 22, 2015 12:15 am

If you define your own __init__, you should call the super class' __init__. If I remember correctly (not at home for a few more days), pylint (which is a code checker/verifier) by default wants you to define __init__ if you are inheriting from anything other than 'object'.
Image
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Postby BackRaw » Mon Jun 22, 2015 12:32 am

satoon101 wrote:If you define your own __init__, you should call the super class' __init__. If I remember correctly (not at home for a few more days), pylint (which is a code checker/verifier) by default wants you to define __init__ if you are inheriting from anything other than 'object'.

Great, thanks for clearing up :)
My Github repositories:

Source.Python: https://github.com/backraw
User avatar
Mahi
Senior Member
Posts: 236
Joined: Wed Aug 29, 2012 8:39 pm
Location: Finland

Postby Mahi » Mon Jun 22, 2015 12:34 am

Satoon might be right about the pylint, but no, you don't have to define __init__ in a subclass if it doesn't do anything different from its super class's __init__. There's absolutely no benefit of doing this. Also, I couldn't find anything about this on PEP8, nor do I personally see why would you even want to do it (looking at you pylint). Just leave the subclass's __init__ out! :)

And Satoon is correct about always calling super's __init__ in a subclass, if you need a separate __init__ method in the subclass.

What comes to dicts and other Python built-ins: they're classes just like any other, and therefore all this applies to them too. So you can just skip their __init__ too if you're subclassing them. However, you must call their __init__ in the subclass's __init__, if you define one.
User avatar
satoon101
Project Leader
Posts: 2703
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Mon Jun 22, 2015 12:37 am

You might try installing pylint yourself to check your code. If you notice, we use 4 different code checkers for the SP API (pep8, pep257, pyflakes, and pylint). Sometimes they conflict, so use your best judgment. And, you can also modify the checkers (especially pylint) to your own specifications, if need be.
Image
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Postby BackRaw » Mon Jun 22, 2015 12:46 am

Now I'm confused lol. I have two occasions where I need subclassing. First I subclass TickRepeat (this is where __init__ needs to be implemented)

Syntax: Select all

class _SpawnProtectionRepeat(TickRepeat): 

"""Adds a messaging logic to TickRepeat"""

def __init__(self, player):
"""Called on instantiation."""
# Call TickRepeat's constructor
super(_SpawnProtectionRepeat, self).__init__(self._message)

# ...
Next is dict, and here I'm not sure, Mahi - is it safe to leave __init__ out?

Syntax: Select all

class SpawnProtectionRepeats(dict):

"""Extends dict to utilize players' repeat instances."""

def __init__(self):
"""Called on instantiation."""
# Call dict's constructor
super(SpawnProtectionRepeats, self).__init__()
I'll check my code using pylint in a minute.
My Github repositories:

Source.Python: https://github.com/backraw
User avatar
Mahi
Senior Member
Posts: 236
Joined: Wed Aug 29, 2012 8:39 pm
Location: Finland

Postby Mahi » Mon Jun 22, 2015 12:49 am

BackRaw wrote:Next is dict, and here I'm not sure, Mahi - is it safe to leave __init__ out?
Yes, and you absolutely should. Only define an __init__ if it differs from the super class's __init__.

Edit: Regardless of what pylint says, unless someone can reason why it complains about this.
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Postby BackRaw » Mon Jun 22, 2015 12:52 am

Mahi wrote:
BackRaw wrote:Next is dict, and here I'm not sure, Mahi - is it safe to leave __init__ out?
Yes, and you absolutely should. Only define an __init__ if it differs from the super class's __init__.


Cool, thanks.
My Github repositories:

Source.Python: https://github.com/backraw
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Postby BackRaw » Mon Jun 22, 2015 12:57 am

Pylint doesn't complain about the missing __init__, however it complains about names not being correct:

Code: Select all

C: 66, 0: Invalid constant name "messages" (invalid-name)
C:137, 4: Invalid constant name "saycommand" (invalid-name)
E:171,16: Instance of '_SpawnProtectionRepeat' has no 'remaining' member (no-member)
E:174,95: Instance of '_SpawnProtectionRepeat' has no 'remaining' member (no-member)
R:148, 0: Too few public methods (1/2) (too-few-public-methods)
C:218, 0: Invalid constant name "spawnprotection_repeats" (invalid-name)
Which I don't get. Why is messages a 'wrong' name to use for a variable? It is used as

Syntax: Select all

messages = LangStrings('{0}/messages'.format(info.basename))

Whole script: https://github.com/backraw/flashfunsp/blob/master/addons/source-python/plugins/flashfunsp/flashfunsp.py
My Github repositories:

Source.Python: https://github.com/backraw
User avatar
satoon101
Project Leader
Posts: 2703
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Mon Jun 22, 2015 1:43 am

That error is because pylint is setup so that all global variables are considered "constants". We actually modified the constant regex used to allow for lower case because of that exact issue.

Notice the const-rgx in this line:
https://github.com/Source-Python-Dev-Team/Source.Python/blob/master/checker.bat#L55
Image
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Postby BackRaw » Mon Jun 22, 2015 2:56 pm

Alright that makes sense. I'll try something like that then.
My Github repositories:

Source.Python: https://github.com/backraw
User avatar
satoon101
Project Leader
Posts: 2703
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Mon Jun 22, 2015 3:59 pm

You can do that in the command line or in the .pylintrc file like this:
https://github.com/satoon101/PluginHelpers/blob/master/plugin_helpers/tools/.pylintrc
Image

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 70 guests