Instance Attribute Attribute_Name Defined Outside _Init_

why is defining an object variable outside of __init__ frowned upon?

Python allows you to add and delete attributes at any time. There are two problems with not doing it at __init__

  1. Your definitions aren't all in one place
  2. If you use it in a function, you may not have defined it yet

Note that you can fix the above problem of setting an attribute later by defining it in __init__ as:

self.dontknowyet = None      # Everyone is happy

Python - instance attribute defined outside __init__()

It's always important to keep in mind that not all Warnings require fixing. Warnings are just Warnings. They are supposed to point out a specific part of the code because it's a "common" source of problems. But sometimes you need/want to do it that way.

I could fix the warning by adding 8 definition lines assigning None to all the variables

That's just "silencing" the Warnings, in my opinion that's just as good as ignoring the Warnings.

So what is the right thing to do?

The right way would be to just use __init__. I did a quick test and I don't have any problems.

However that's just an example how one could do it. I haven't checked what Frame wants as arguments for __init__ so it could lead to conflicts:

from tkinter import *
from tkinter import ttk

class Autocomplete(Frame, object):
def __init__(self, *args, **kwargs):
width, height, entries = kwargs.pop('width'), kwargs.pop('height'), kwargs.pop('entries')
super(Autocomplete, self).__init__(*args, **kwargs)
self.list = []
self._entries = entries
self.listbox_height = height
self.entry_width = width
self.text = StringVar()
self.entry = ttk.Entry(self, textvariable=self.text, width=self.entry_width)
self.frame = Frame(self)
self.listbox = Listbox(self.frame, height=self.listbox_height, width=self.entry_width)
self.dropdown = Listbox(self.frame, height=self.listbox_height, width=self.entry_width, background="#cfeff9",
takefocus=0)
self.entry.pack()
self.frame.pack()
self.listbox.grid(column=0, row=0, sticky=N)
self.dropdown.grid(column=0, row=0, sticky=N)
self.dropdown.grid_forget()

root = Frame(Tk())
autocomplete = Autocomplete(root, width=74, height=10, entries=entries)
root.pack()
autocomplete.pack()
mainloop()

This inspection detects instance attribute definition outside __init__ method PyCharm

Yes it's generally considered a good practice to explicitly define/declare all your attributes in the __init__ function, this way you have a quick list of all used (or unused) attributes in the class.

class Firebird:

username= "..."
password= "..."

def __init__(self, archive):
self.archive = archive
self.connection = None

def connect(self):
try:
self.connection = connect(dsn=self.archive, user=self.username, password=self.password)
except Error, e:
print "Failed to connect to database", e
exit(0)

Defining a class property within __init__ as opposed to within another class method -- python

I think it's a best practice to define all of your attributes up front, even if you're going to redefine them later. When I read your code, I want to be able to see your data structures. If there's some attribute hidden in a method that only becomes defined under certain circumstances, it makes it harder to understand the code.

If it is inconvenient or impossible to give an attribute it's final value, I recommend at least initializing it to None. This signals to the reader that the object includes that attribute, even if it gets redefined later.

class exampleClass:
"""
This is an example class to demonstrate my question to stack exchange
"""

def __init__( self, fileName ):
# Note: this will be modified when a file is loaded
self.name = None

exampleClass.loadData( self, fileName )

Another choice would be for loadData to return the value rather than setting it, so your init might look like:

def __init__(self, fileName):
self.name = self.loadData(fileName)

I tend to think this second method is better, but either method is fine. The point is, make your classes and objects as easy to understand as possible.

pylint attribute-defined-outside-init; but attributes are in __init__() method

Although correct, this still did not do the trick. I ended up reinstalling pylint and now the error is not showing anymore.

How do I avoid the self.x = x; self.y = y; self.z = z pattern in __init__?

Edit:
If you have python 3.7+ just use dataclasses

A decorator solution that keeps the signature:

import decorator
import inspect
import sys

@decorator.decorator
def simple_init(func, self, *args, **kws):
"""
@simple_init
def __init__(self,a,b,...,z)
dosomething()

behaves like

def __init__(self,a,b,...,z)
self.a = a
self.b = b
...
self.z = z
dosomething()
"""

#init_argumentnames_without_self = ['a','b',...,'z']
if sys.version_info.major == 2:
init_argumentnames_without_self = inspect.getargspec(func).args[1:]
else:
init_argumentnames_without_self = tuple(inspect.signature(func).parameters.keys())[1:]

positional_values = args
keyword_values_in_correct_order = tuple(kws[key] for key in init_argumentnames_without_self if key in kws)
attribute_values = positional_values + keyword_values_in_correct_order

for attribute_name,attribute_value in zip(init_argumentnames_without_self,attribute_values):
setattr(self,attribute_name,attribute_value)

# call the original __init__
func(self, *args, **kws)

class Test():
@simple_init
def __init__(self,a,b,c,d=4):
print(self.a,self.b,self.c,self.d)

#prints 1 3 2 4
t = Test(1,c=2,b=3)
#keeps signature
#prints ['self', 'a', 'b', 'c', 'd']
if sys.version_info.major == 2:
print(inspect.getargspec(Test.__init__).args)
else:
print(inspect.signature(Test.__init__))


Related Topics



Leave a reply



Submit