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.

Python Decorators

Table of Contents

  • What are decorators in Python?
  • Prerequisites for learning Decorators
  • Getting back to Decorators
  • Decorating Functions with Parameters
  • Chaining Decorators in Python

What are decorators in Python?

Python has an interesting feature called decorators to add functionality to an existing code.

This is also called metaprogramming as a part of the program tries to modify another part of the program at compile time.


Prerequisites for learning decorators

In order to understand about decorators, we must first know a few basic things in Python.

We must be comfortable with the fact that, everything in Python (Yes! Even classes), are objects. Names that we define are simply identifiers bound to these objects. Functions are no exceptions, they are objects too (with attributes). Various different names can be bound to the same function object.

Here is an example.

def first(msg):
   print(msg)

first("Hello")
second = first
second("Hello")

When you run the code, both functions first and second gives same output. Here, the names first and second refer to the same function object.

Now things start getting weirder.

Functions can be passed as arguments to another function.

If you have used functions like mapfilter and reduce in Python, then you already know about this.

Such function that take other functions as arguments are also called higher order functions. Here is an example of such a function.

def inc(x):
     return x + 1

def dec(x):
     return x - 1

def operate(func, x):
    result = func(x)
    return result

We invoke the function as follows.

>>> operate(inc,3)
4
>>> operate(dec,3)
2

Furthermore, a function can return another function.

def is_called():
     def is_returned():
            print("Hello")
     return is_returned

new = is_called()

new()
#Outputs "Hello"

Here, is_returned() is a nested function which is defined and returned, each time we call is_called().

Note: Finally, we must know about closures in Python.


Getting back to Decorators

Functions and methods are called callable as they can be called.

In fact, any object which implements the special method __call__() is termed callable. So, in the most basic sense, a decorator is a callable that returns a callable.

Basically, a decorator takes in a function, adds some functionality and returns it.

def make_pretty(func):
      def inner():
           print("I got decorated")
           func()
      return inner

def ordinary():
    print("I am ordinary")
When you run the following codes in shell,
>>> ordinary()
I am ordinary

>>> # let's decorate this ordinary function
>>> pretty = make_pretty(ordinary)
>>> pretty()
I got decorated
I am ordinary

In the example shown above, make_pretty() is a decorator. In the assignment step.

pretty = make_pretty(ordinary)

The function ordinary() got decorated and the returned function was given the name pretty.

We can see that the decorator function added some new functionality to the original function. This is similar to packing a gift. The decorator acts as a wrapper. The nature of the object that got decorated (actual gift inside) does not alter. But now, it looks pretty (since it got decorated).

Generally, we decorate a function and reassign it as,

ordinary = make_pretty(ordinary).

This is a common construct and for this reason, Python has a syntax to simplify this.

We can use the @ symbol along with the name of the decorator function and place it above the definition of the function to be decorated. For example,

@make_pretty
def ordinary():
    print("I am ordinary")

is equivalent to

def ordinary():
    print("I am ordinary")
ordinary = make_pretty(ordinary)

This is just a syntactic sugar to implement decorators.


Decorating Functions with Parameters

The above decorator was simple and it only worked with functions that did not have any parameters. What if we had functions that took in parameters like below?

def divide(a, b):
    return a/b

This function has two parameters, a and b. We know, it will give error if we pass in b as 0.

>>> divide(2,5)
0.4
>>> divide(2,0)
Traceback (most recent call last):
...
ZeroDivisionError: division by zero

Now let’s make a decorator to check for this case that will cause the error.

def smart_divide(func):
      def inner(a,b):
             print("I am going to divide",a,"and",b)
             if b == 0:
                   print("Whoops! cannot divide")
                   return
            return func(a,b)
       return inner

@smart_divide
def divide(a,b):
    return a/b

This new implementation will return None if the error condition arises.

>>> divide(2,5)
I am going to divide 2 and 5
0.4

>>> divide(2,0)
I am going to divide 2 and 0
Whoops! cannot divide

In this manner we can decorate functions that take parameters.

A keen observer will notice that parameters of the nested inner() function inside the decorator is same as the parameters of functions it decorates. Taking this into account, now we can make general decorators that work with any number of parameter.

In Python, this magic is done as function(*args, **kwargs). In this way, args will be the tuple of positional arguments and kwargs will be the dictionary of keyword arguments. An example of such decorator will be.

def works_for_all(func):
    def inner(*args, **kwargs):
        print("I can decorate any function")
        return func(*args, **kwargs)
    return inner

Chaining Decorators in Python

Multiple decorators can be chained in Python.

This is to say, a function can be decorated multiple times with different (or same) decorators. We simply place the decorators above the desired function.

def star(func):
        def inner(*args, **kwargs):
               print("*" * 30)
               func(*args, **kwargs)
               print("*" * 30)
         return inner

def percent(func):
        def inner(*args, **kwargs):
               print("%" * 30)
               func(*args, **kwargs)
               print("%" * 30)
         return inner

@star
@percent
def printer(msg):
     print(msg)
printer("Hello")

This will give the output.

******************************
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Hello
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
******************************

The above syntax of,

@star
@percent
def printer(msg):
    print(msg)

is equivalent to

def printer(msg):
    print(msg)
printer = star(percent(printer))

The order in which we chain decorators matter. If we had reversed the order as,

@percent
@star
def printer(msg):
    print(msg)

The execution would take place as,

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
******************************
Hello
******************************
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

What does an empty return in Python mean?

Example program:

 if hasattr(self, 'moved_away'):
        return        # and here code continues

Solution 1:

It means it will return None. You could remove the return and it would still return None because all functions that don’t specify a return value in python will by default return None.

In this particular case it means the code will go no further if the object has the attribute 'moved_away', without the return any code below would be evaluated even if the if statement evaluated to True.

So you can think of it as being similar to a break statement in a loop when you have a condition you want to exit the loop on, without the break the code would continue to be evaluated.

Solution 2:

return exits the current methods.

So, here it will stop the execution & return None.

Property in python

Table of Contents

  • An Example To Begin With
  • Using Getters and Setters
  • The Power of @property
  • Digging Deeper into Property

Python has a great concept called property which makes the life of an object oriented programmer much simpler.

Before defining and going into details of what @property is, let us first build an intuition on why it would be needed in the first place.


An Example To Begin With

Let us assume that you decide to make a class that could store the temperature in degree Celsius. It would also implement a method to convert the temperature into degree Fahrenheit. One way of doing this is as follows.

# program
class Celsius:
    def __init__(self, temperature = 0):
        self.temperature = temperature
    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32

We could make objects out of this class and manipulate the attribute temperature as we wished. Try these on Python shell.

>>> # create new object
>>> man = Celsius()

>>> # set temperature
>>> man.temperature = 37

>>> # get temperature
>>> man.temperature
37

>>> # get degrees Fahrenheit
>>> man.to_fahrenheit()
98.60000000000001

The extra decimal places when converting into Fahrenheit is due to the floating point arithmetic error (try 1.1 + 2.2 in the Python interpreter).

Whenever we assign or retrieve any object attribute like temperature, as show above, Python searches it in the object’s __dict__ dictionary.

>>> man.__dict__
{'temperature': 37}

Therefore, man.temperature internally becomes man.__dict__['temperature'].

Now, let’s further assume that our class got popular among clients and they started using it in their programs. They did all kinds of assignments to the object.

One fateful day, a trusted client came to us and suggested that temperatures cannot go below -273 degree Celsius (students of thermodynamics might argue that it’s actually -273.15), also called the absolute zero. He further asked us to implement this value constraint. Being a company that strive for customer satisfaction, we happily heeded the suggestion and released version 1.01 (an upgrade of our existing class).


Using Getters and Setters

An obvious solution to the above constraint will be to hide the attribute temperature (make it private) and define new getter and setter interfaces to manipulate it. This can be done as follows.

# program
class Celsius:
    def __init__(self, temperature = 0):
        self.set_temperature(temperature)
   def to_fahrenheit(self):
        return (self.get_temperature() * 1.8) + 32
   # new update
   def get_temperature(self):
      return self._temperature
   def set_temperature(self, value):
      if value < 273:
          raise ValueError(“Temperature below -273 is not possible”)
      self._temperature = value
We can see above that new methods get_temperature() and set_temperature() were defined and furthermore, temperature was replaced with _temperature. An underscore (_) at the beginning is used to denote private variables in Python.
>>> c = Celsius(-277)
Traceback (most recent call last):
...
ValueError: Temperature below -273 is not possible

>>> c = Celsius(37)
>>> c.get_temperature()
37
>>> c.set_temperature(10)

>>> c.set_temperature(-300)
Traceback (most recent call last):
...
ValueError: Temperature below -273 is not possible

This update successfully implemented the new restriction. We are no longer allowed to set temperature below -273.

Please note that private variables don’t exist in Python. There are simply norms to be followed. The language itself don’t apply any restrictions.

>>> c._temperature = -300
>>> c.get_temperature()
-300

But this is not of great concern. The big problem with the above update is that, all the clients who implemented our previous class in their program have to modify their code from obj.temperature to obj.get_temperature() and all assignments like obj.temperature = val to obj.set_temperature(val).

This refactoring can cause headaches to the clients with hundreds of thousands of lines of codes.

All in all, our new update was not backward compatible. This is where property comes to rescue.


The Power of @property

The pythonic way to deal with the above problem is to use property. Here is how we could have achieved it.

# program
class Celsius:
  def __init__(self, temperature = 0):
      self.temperature = temperature
  def to_fahrenheit(self):
      return (self.temperature * 1.8) + 32
  def get_temperature(self):
     print(“Getting value”)
     return self._temperature
  def set_temperature(self, value):
     if value < 273:
         raise ValueError(“Temperature below -273 is not possible”)
     print(“Setting value”)
     self._temperature = value
  temperature = property(get_temperature,set_temperature)

And, issue the following code in shell once you run it.

>>> c = Celsius()

We added a print() function inside get_temperature() and set_temperature() to clearly observe that they are being executed.

The last line of the code, makes a property object temperature. Simply put, property attaches some code (get_temperature and set_temperature) to the member attribute accesses (temperature).

Any code that retrieves the value of temperature will automatically call get_temperature()instead of a dictionary (__dict__) look-up. Similarly, any code that assigns a value to temperature will automatically call set_temperature(). This is one cool feature in Python.

We can see above that set_temperature() was called even when we created an object.

Can you guess why?

The reason is that when an object is created, __init__() method gets called. This method has the line self.temperature = temperature. This assignment automatically called set_temperature().

>>> c.temperature
Getting value
0

Similarly, any access like c.temperature automatically calls get_temperature(). This is what property does. Here are a few more examples.

>>> c.temperature = 37
Setting value

>>> c.to_fahrenheit()
Getting value
98.60000000000001

By using property, we can see that, we modified our class and implemented the value constraint without any change required to the client code. Thus our implementation was backward compatible and everybody is happy.

Finally note that, the actual temperature value is stored in the private variable _temperature. The attribute temperature is a property object which provides interface to this private variable.


Digging Deeper into Property

In Python, property() is a built-in function that creates and returns a property object. The signature of this function is

property(fget=None, fset=None, fdel=None, doc=None)

where, fget is function to get value of the attribute, fset is function to set value of the attribute, fdel is function to delete the attribute and doc is a string (like a comment). As seen from the implementation, these function arguments are optional. So, a property object can simply be created as follows.

>>> property()
<property object at 0x0000000003239B38>

A property object has three methods, getter()setter(), and delete() to specify fgetfset and fdel at a later point. This means, the line

temperature = property(get_temperature,set_temperature)

could have been broken down as

# make empty property
temperature = property()
# assign fget
temperature = temperature.getter(get_temperature)
# assign fset
temperature = temperature.setter(set_temperature)

These two pieces of codes are equivalent.

Programmers familiar with decorators in Python can recognize that the above construct can be implemented as decorators.

We can further go on and not define names get_temperature and set_temperature as they are unnecessary and pollute the class namespace. For this, we reuse the name temperaturewhile defining our getter and setter functions. This is how it can be done.

# program
class Celsius:
    def __init__(self, temperature = 0):
        self._temperature = temperature
    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32
    @property
    def temperature(self):
        print(“Getting value”)
        return self._temperature
   @temperature.setter
    def temperature(self, value):
        if value < 273:
             raise ValueError(“Temperature below -273 is not possible”)
       print(“Setting value”)
       self._temperature = value
The above implementation is both, simple and recommended way to make properties. You will most likely encounter these types of constructs when looking for property in Python.

How can you Get the Google cache age of any URL or web page?

Ans: Use the following URL format:

http://webcache.googleusercontent.com/search?q=cache:URLGOESHERE

Be sure to replace “URLGOESHERE” with the proper web address of the page or site whose cache you want to retrieve and see the time for. For example, to check the Google Webcache age of edureka.co you’d use the following URL:

http://webcache.googleusercontent.com/search?q=cache:edureka.co

What is monkey patching in Python?

Ans: In Python, the term monkey patch only refers to dynamic modifications of a class or module at run-time.

Consider the below example:

# m.py
class MyClass:
   def f(self):
      print "f()"

We can then run the monkey-patch testing like this:

import m
def monkey_f(self):
    print "monkey_f()"

m.MyClass.f = monkey_f
obj = m.MyClass()
obj.f()

The output will be as below:

monkey_f()

As we can see, we did make some changes in the behavior of f() in MyClass using the function we defined, monkey_f(), outside of the module m.