Instantiate a Python class using an object as argument

Asked

Viewed 7,867 times

1

I am starting to work with Python and saw that there is no way to create multiple constructors in the same class. With that I thought I’d move on to the constructor __init__ an object containing class attributes, as in the example:

class Foo(object):
    '''
    classdocs
    '''
    _id = None
    name = None

    def __init__(self, *attrs):
        if attrs:
            for key, value in attrs.iteritems():
                setattr(self, key, value)

    def __getattr__(self, key):
        if(hasattr(self, key)):
            return key
        else:
            return None

    def __setattr__(self, k, v):
        if hasattr(self, k):
            super().__setattr__(k, v)
            return True
        else:
            return False

The problem is that I am not managing to feed my class with the existing attributes, always presents a mistake. When I create a simple class instance without passing attributes and manually define attributes, the class also does not restrict if it does not exist.

from Project.Models.Foo import Foo

c = Foo()

print(c._id)
print(c.name)
print(c.foo)

In doing so I have the error:

Traceback (most recent call last):
  File "F:\Project\src\Project\Test\TestFoo.py", line 7, in <module>
    print(c.foo)
  File "F:\Project\src\Project\Models\Foo.py", line 25, in __getattr__
    if(hasattr(self, key)):

Does anyone have an idea of how I can pass objects to set classes and how I can restrict the get and set if the attribute does not exist?

3 answers

3


In your need in the class initializer, Voce implements key and value. This characterizes dictionary. However the call is using the list notation.

Substitute:

    def __init__(self, *attrs):
    if attrs:
        for key, value in attrs.iteritems():
            setattr(self, key, value)

For:

    def __init__(self, **attrs):
    if attrs:
        for key, value in attrs.iteritems():
            setattr(self, key, value)

And another incongruity is in the implementation of getattr, for the method hasattr(), runs Dundler getattr. This causes the call to loop infinity.

Substitute:

def __getattr__(self, key):
    if(hasattr(self, key)):
        return key
    else:
        return None

For:

def __getattr__(self, key):
    if key in self.__dict__:
        return self.__dict__[key]
    return None

Complete code available at:

https://gist.github.com/britodfbr/02b27c18bddc877ff25d8fdad9be9c0e

  • Cara had already forgotten this question but it certainly solves the problem I had, thank you very much!

3

I answered your other question in Restrict __setattr__ when the attribute does not exist within the Python instance with something that should solve your problem.

has some concept errors in how you are writing what you want - But before addressing your question it’s important to keep in mind that "Python is not Java" in another statically typed language: you can add attributes to an existing object is a language Feature - and generational, although there are forms, you don’t have to worry about artificially placing these restrictions: realize that the only people who might want to paste more attributes into an object are other programmers - and they might want to have a use for those attributes - if there is no use, there is no reason to want to set such attributes.

That said - you’re confused about how to use "objects" and dictionaries - in Python - not as in Javascript - objects and dictionaries are different - the latter have features that we call "Mapping" - and although we can set and read attributes dynamically in objects, if the attribute name is not fixed in the source code, it is best to use dictionaries for this -

In the case of your example, simply pass "attrs" as a dictionary - you don’t need the * -

def __init__(self, attrs):        
    for key, value in attrs.items():
        setattr(self, key, value)

Again - if you want to restrict access to attributes, check my answer in the question linked above.

  • I know that Python is not java, but that doesn’t mean that my concept of OO aimed at a class that was built in Java cannot be applied in Python. I understand that the only ones who will change the attributes of an object are the programmers but if you have a team where 1 designer structures the project, they can only change according to the class defined by the designer

  • 1

    "they can only change according to the class defined by the designer -" - exactly - and in Python it is understood that the programmers are 'consenting Adults' - they do not need the language to force them to a restriction that has been agreed in the documentation or by convention in a project.

1

My solution, after some headaches was to define all the attributes I could have within this class directly in the method __init__. What I realized was that, unlike Java, Python does not depend on a specific number of variables on startup, as long as they have default values. Thus

class Teste:
    foo = None
    bar = None
def __init__(self, foo=None, bar=None)
    self.foo = foo
    self.bar = bar

In doing so, regardless of whether I declare a simple t = Teste() it will not force me to have passed any parameter in the instance.

Browser other questions tagged

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