Python setattr()

The setattr() method sets the value of given attribute of an object.

The syntax of setattr() method is:

setattr(object, name, value)

If you want to get an attribute of an object, use getattr().


setattr() Parameters

The setattr() method takes three parameters:

  • object – object whose attribute has to be set
  • name – string which contains the name of the attribute to be set
  • value – value of the attribute to be set

Return value from setattr()

The setattr() method returns None.


Example 1: How setattr() works in Python?

class Person:
   name = 'Adam'

p = Person()
print('Before modification:', p.name)

# setting name to 'John'
setattr(p, 'name', 'John')

print('After modification:', p.name)

When you run the program, the output will be:

Before modification: Adam
After modification: John

Example 2: setattr() when named attribute is not found and setting attribute to None

However, this is only possible if the object implements __dict__() method.

You can check if it does by using dir() method.

class Person:
     name = 'Adam'

p = Person()


# setting attribute name to None
setattr(p, 'name', None)
print('Name is:', p.name)


# setting an attribute not present
# in Person
setattr(p, 'age', 23)
print('Age is:', p.age)

When you run the program, the output will be:

Name is: None
Age is: 23
Advertisements

Importing Python Modules and circular dependency explanation

Introduction

The import and from-import statements are a constant cause of serious confusion for newcomers to Python. Luckily, once you’ve figured out what they really do, you’ll never have problems with them again.

This note tries to sort out some of the more common issues related to importand from-import and everything.

There are Many Ways to Import a Module

Python provides at least three different ways to import modules. You can use the import statement, the from statement, or the builtin __import__ function. (There are more contrived ways to do this too, but that’s outside the scope for this small note.)

Anyway, here’s how these statements and functions work:

  • import X imports the module X, and creates a reference to that module in the current namespace. Or in other words, after you’ve run this statement, you can use X.name to refer to things defined in module X.
  • from X import * imports the module X, and creates references in the current namespace to all public objects defined by that module (that is, everything that doesn’t have a name starting with “_”). Or in other words, after you’ve run this statement, you can simply use a plain name to refer to things defined in module X. But X itself is not defined, so X.namedoesn’t work. And if name was already defined, it is replaced by the new version. And if name in X is changed to point to some other object, your module won’t notice.
  • from X import a, b, c imports the module X, and creates references in the current namespace to the given objects. Or in other words, you can now use a and b and c in your program.
  • Finally, X = __import__(‘X’) works like import X, with the difference that you 1) pass the module name as a string, and 2) explicitly assign it to a variable in your current namespace.

Which Way Should I Use?

Short answer: always use import.

As usual, there are a number of exceptions to this rule:

  • The Module Documentation Tells You To Use from-import. The most common example in this category is Tkinter, which is carefully designed to add only the widget classes and related constants to your current namespace. Using import Tkinter only makes your program harder to read; something that is generally a bad idea.
  • You’re Importing a Package Component. When you need a certain submodule from a package, it’s often much more convenient to write from io.drivers import zip than import io.drivers.zip, since the former lets you refer to the module simply as zip instead of its full name. In this case, the from-import statement acts pretty much like a plain import, and there’s not much risk for confusion.
  • You Don’t Know the Module Name Before Execution. In this case, use __import__(module) where module is a Python string. Also see the next item.
  • You Know Exactly What You’re Doing. If you think you do, just go ahead and use from-import. But think twice before you ask for help

What Does Python Do to Import a Module?

When Python imports a module, it first checks the module registry (sys.modules) to see if the module is already imported. If that’s the case, Python uses the existing module object as is.

Otherwise, Python does something like this:

  1. Create a new, empty module object (this is essentially a dictionary)
  2. Insert that module object in the sys.modules dictionary
  3. Load the module code object (if necessary, compile the module first)
  4. Execute the module code object in the new module’s namespace. All variables assigned by the code will be available via the module object.

This means that it’s fairly cheap to import an already imported module; Python just has to look the module name up in a dictionary.

Import Gotchas

Using Modules as Scripts

If you run a module as a script (i.e. give its name to the interpreter, rather than importing it), it’s loaded under the module name __main__.

If you then import the same module from your program, it’s reloaded and reexecuted under its real name. If you’re not careful, you may end up doing things twice.

Circular Imports

In Python, things like defclass, and import are statements too.

Modules are executed during import, and new functions and classes won’t appear in the module’s namespace until the def (or class) statement has been executed.

This has some interesting implications if you’re doing recursive imports.

Consider a module X which imports module Y and then defines a function called spam:

    # module X

    import Y

    def spam():
        print "function in module x"

If you import X from your main program, Python will load the code for X and execute it. When Python reaches the import Y statement, it loads the code for Y, and starts executing it instead.

At this time, Python has installed module objects for both X and Y in sys.modules. But X doesn’t contain anything yet; the def spam statement hasn’t been executed.

Now, if Y imports X (a recursive import), it’ll get back a reference to an empty Xmodule object. Any attempt to access the X.spam function on the module level will fail.

    # module Y

    from X import spam # doesn't work: spam isn't defined yet!

Note that you don’t have to use from-import to get into trouble:

    # module Y

    import X

    X.spam() # doesn't work either: spam isn't defined yet!

To fix this, either refactor your program to avoid circular imports (moving stuff to a separate module often helps), or move the imports to the end of the module (in this case, if you move import Y to the end of module X, everything will work just fine).

Python id()

The id() function returns identity (unique integer) of an object.

The syntax of id() is:

id(object)

id() Parameters

The id() function takes a single parameter object.


Return Value from id()

The id() function returns identity of the object. This is an integer which is unique for the given object and remains constant during its lifetime.


Example 1: How id() works?

class Foo:
   b = 5

dummyFoo = Foo()
print('id of dummyFoo =',id(dummyFoo))

When you run the program, the output will something like:

id of dummyFoo = 140343867415240

More Examples on id()

print('id of 5 =',id(5))

a = 5
print('id of a =',id(a))

b = a
print('id of b =',id(b))

c = 5.0
print('id of c =',id(c))

When you run the program, the output will be something like:

id of 5 = 140472391630016
id of a = 140472391630016
id of b = 140472391630016
id of c = 140472372786520

It’s important to note that everything in Python is an object, even numbers and Classes.

Hence, integer 5 has a unique id. The id of the integer 5 remains constant during the lifetime. Similar is the case for float 5.5 and other objects.

What is Assertion?

Assertions are statements that assert or state a fact confidently in your program. For example, while writing a division function, you’re confident the divisor shouldn’t be zero, you assert divisor is not equal to zero.

Assertions are simply boolean expressions that checks if the conditions return true or not. If it is true, the program does nothing and move to the next line of code. However, if it’s false, the program stops and throws an error.

It is also a debugging tool as it brings the program on halt as soon as any error is occurred and shows on which point of the program error has occurred.

We can be clear by looking at the flowchart below:

Python Assert Flowchart


Python assert Statement

Python has built-in assert statement to use assertion condition in the program. assertstatement has a condition or expression which is supposed to be always true. If the condition is false assert halts the program and gives an AssertionError.

Syntax for using Assert in Pyhton:

assert <condition>
assert <condition>,<error message>

In Python we can use assert statement in two ways as mentioned above.

  1. assert statement has a condition and if the condition is not satisfied the program will stop and give AssertionError.
  2. assert statement can also have a condition and a optional error message. If the condition is not satisfied assert stops the program and gives AssertionError along with the error message.

Let’s take an example, where we have a function which will calculate the average of the values passed by the user and the value should not be an empty list. We will use assertstatement to check the parameter and if the length is of the passed list is zero, program halts.

Example 1: Using assert without Error Message

def avg(marks):
    assert len(marks) != 0
    return sum(marks)/len(marks)

mark1 = []

print("Average of mark1:",avg(mark1))

When we run the above program, the output will be:

AssertionError

We got an error as we passed an empty list mark1 to assert statement, the condition became false and assert stops the program and give AssertionError.

Now let’s pass another list which will satisfy the assert condition and see what will be our output.


Example 2: Using assert with error message

def avg(marks):
      assert len(marks) != 0,"List is empty."
      return sum(marks)/len(marks)

mark2 = [55,88,78,90,79]
print("Average of mark2:",avg(mark2))

mark1 = []
print("Average of mark1:",avg(mark1))

When we run the above program, the output will be:

Average of mark2: 78.0
AssertionError: List is empty.

We passed a non-empty list mark2 and also an empty list mark1 to the avg() function and we got output for mark2 list but after that we got an error AssertionError: List is empty. The assert condition was satisfied by the mark2 list and program to continue to run. However, mark1 doesn’t satisfy the condition and gives an AssertionError.


Key Points to Remember

  • Assertions are the condition or boolean expression which are always supposed to be true in the code.
  • assert statement takes an expression and optional message.
  • assert statement is used to check types, values of argument and the output of the function.
  • assert statement is used as debugging tool as it halts the program at the point where an error occurs.