Instantiating a class in Python using an object as an argument

1

I'm starting to work with Python and I've seen that there's no way to create multiple con- trollers in the same class. With this I thought of passing to the% co_conductor an object containing the attributes of the class, 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 can not feed my class with the existing attributes, it always presents an error. When I create a simple instance of the class without passing attributes and manually define the attributes, the class also does not constrain if it does not exist.

from Project.Models.Foo import Foo

c = Foo()

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

When doing this 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 how I can pass objects to classes and how can I restrict the get and set if the attribute does not exist?

    
asked by anonymous 06.09.2016 / 16:51

3 answers

3

In your need in the class initializer, you implement key and value. This features dictionary. While the call is using the notation for lists.

Replace:

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

By:

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

And another inconsistency is in the implementation of getattr , because the hasattr() method runs dundler getattr. This causes the call to loop in infinite.

Replace:

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

By:

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

Complete code available at:

link

    
17.07.2017 / 16:50
3

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

Have some misconceptions on how you're writing what you want - But before addressing your question it is important to keep in mind that "Python is not Java" in another statically typed language: you can add attributes to an already existing object is a feature of the language - and generally, although there are shapes, you do not need beware of putting those restrictions artificially: realize that the only people who may want to put more attributes into an object are other programmers - and they may want to have a use for those attributes - if there is no use, there is no reason to want to set such constraints attributes.

That said - you are confused about using "objects" and dictionaries - in Python - not like Javascript - objects and dictionaries are different - the latter have characteristics that we call "mapping" - and although we can to read attributes dynamically on objects, if attribute names are not fixed in source code, it is best to use dictionaries for this -

In the case of your example, simply pass "attrs" as a dictionary - you do not need * -

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 link above.

    
07.09.2016 / 12:50
1

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

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

Doing this, regardless if I declare a simple t = Teste() it will not force me to have passed any parameter in the instance.

    
08.09.2016 / 16:02