Undefined variable with import python

Asked

Viewed 562 times

0

I am having problems with the inheritance of attributes between a mother class and a daughter class that are in two different files.

When using them in the same file no error is displayed:

cls_usuario.py file:

    class Usuario:
    def __init__(self, id_usuario, nome, login, senha, tipo_conta, departamento, cargo, situacao):
        self._id_usuario = id_usuario
        self._nome_usuario = nome
        self._login_usuario = login
        self._senha_usuario = senha
        self._tipo_conta_usuario = tipo_conta 
        self._departamento_usuario = departamento
        self._cargo_usuario = cargo
        self._situacao_usuario = situacao    

class Administrador(cls_usuario.Usuario):
    def __init__(self, id_administrador):
        super().__init__(id_usuario, nome, login, senha, tipo_conta, departamento, cargo, situacao)
        self.id_administrador = id_administrador

The problem arises when I try to separate the two classes into different files, because I would like to make my project more organized, besides having to use the mother class in several other classes.

cls_usuario.py file - version 2:

    class Usuario:
    def __init__(self, id_usuario, nome, login, senha, tipo_conta, departamento, cargo, situacao):
        self._id_usuario = id_usuario
        self._nome_usuario = nome
        self._login_usuario = login
        self._senha_usuario = senha
        self._tipo_conta_usuario = tipo_conta 
        self._departamento_usuario = departamento
        self._cargo_usuario = cargo
        self._situacao_usuario = situacao  

cls_admin.py file:

import cls_usuario 

class Administrador(cls_usuario.Usuario):
    def __init__(self, id_administrador):
        #super().__init__(id_usuario, nome, login, senha, tipo_conta, departamento, cargo, situacao)
        self.id_administrador = id_administrador

Imagem com os erros exibidos

  • Something important to remember in python is that files do not represent organization. In the vast majority of times separating into files will leave more messy than organized. Always look to split into files when code responsibilities are different, when they do completely different things. This is so true in the language that it is quite common for you to see entire libraries implemented in just one file.

  • On the issue, consider: to create a user I would need to provide name, login, password, etc. To create an administrator I would only need the id. What would be the name of this administrator? You called the method __init__ passing variables that do not exist in the class Administrador.

  • The way you posted - apart from the wrong identations, this error will not occur - I suppose in the code that has these errors, your line calling super Don’t comment on it, okay? (The serros alias that are not even of the language, are of some tool of code verification - the language would give a Nameerror in the first variable inexistent without indicating the others)

1 answer

3


The problem will happen if it is like - and no matter if it is in the same file or not:

import cls_usuario 

class Administrador(cls_usuario.Usuario):
    def __init__(self, id_administrador):
        super().__init__(id_usuario, nome, login, senha, tipo_conta, departamento, cargo, situacao)
        self.id_administrador = id_administrador

(I decoded the first line of __init__ with the call to super).

Well, the names id_usuario, nome, and the other arguments you want to pass in the call to superclass do not exist in that daughter class. There is no magic there - your method__init__ is only receiving the parameter id_administrador. It would have access to other information, such as class attributes (self._nome, etc....) if the superclass was initialized and configured these parameters.

You have two options here: Or declares all parameters in full in the child class, declaring all the names in the __init__:

class Administrador(Usuario):
    def __init__(self, id_usuario, nome, login, senha, tipo_conta, departamento, cargo, situacao, id_administrador):
        super().__init__(id_usuario, nome, login, senha, tipo_conta, departamento, cargo, situacao)
        self.id_administrador = id_administrador

Or uses a generic signature, which takes any number of sequential arguments, and any number of named arguments, and requires the parameter you need in the subclass, id_administrador, to be sent with name - that is, it could not be sent as a positional argument. In fact, for a class receiving so many parameters it is not very healthy to make the call with positional arguments - it is best to make the call always with the name of the same parameters in order to avoid position confusion when typing, and make it possible to check the order. (i.e., instilling the user with a call like:

u = Usuario(id_usuario=id_usuario, nome=nome, login=login....) instead of Usuario(id_usuario, nome, login....)

Anyway, in that case you could leave your __init__ of the subclass thus:

class Administrador(Usuario):
    def __init__(self, *args, *, id_administrador, **kwargs):
        super().__init__(*args, **kwargs)
        self.id_administrador = id_administrador

Just two more considerations: this would break in the same way inside the same file - unless your wrong identation here in the question reflects an even more wrong identation in your code and you declared the subclass nested within the method __init__ superclass (in which case the parameters would be visible as "nonlocal variables").

The second: you should not indicate that all these parameters are "private", that is, prefix them with "_", unless this actually has a practical use. As opposed to using two __, would not be wrong if the intention really is that no code outside the class should read or write in any of these attributes, but even if it is not wrong, it is strange.

  • So far the following code is solving my problem: class Administrator(User): def init(self, id_usuario, name, login, password, account type, department, position, id_admin): super().init(id_user, name, login, password, account type, department, position, location) self.id_administrator = id_admin But the example with *args and *kwargs seems to be more interesting, however, invalid syntax appears. Could you give a more detailed explanation?

  • 1

    The syntax daresposta works - are two asterisks before the "kwargs" - the detailed explanation of what they are can be found in other places - I’ll find a link and put here - is better than re-write.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.