How is the 'is' keyword implemented in Python?
Testing strings with is
only works when the strings are interned. Unless you really know what you're doing and explicitly interned the strings you should never use is
on strings.
is
tests for identity, not equality. That means Python simply compares the memory address a object resides in. is
basically answers the question "Do I have two names for the same object?" - overloading that would make no sense.
For example, ("a" * 100) is ("a" * 100)
is False. Usually Python writes each string into a different memory location, interning mostly happens for string literals.
Does Python's `in` keyword perform a linear search?
Python's in
operator calls the __contains__
magic function on the container. That is implemented in different ways for different containers.
For str
ings, list
s and tuple
s, it's a linear search (O(N)
), though since it's implemented in C it will probably be faster than the pure-python one you have in your question.
For a set
s and dict
s, it's a hash-table lookup, which is much faster (O(1)
average case).
Other containers will have different performance characteristics. I don't think there are any in the standard library, but a balanced tree data structure would probably be O(log N)
.
Behaviour of is keyword in python?
The is
keyword in python is used to test if two variables refer to the same object. It returns True
if the two variable are referring to same object otherwise it returns False
.
For Example consider the class
named A
:
class A:
pass
Case 1:
x = A() #--> create instance of class A
y = A() #--> create instance of class A
>>> x is y
>>> False
Case 2:
x = A() #--> create instance of class A
y = x #--> here y refers to the instance of x
>>> x is y
>>> True
Basically two variables refer to same object if they are referring to same memory location. You can check the identities of the variable by using the built in function in python called id()
, this function returns the identity of the object (address of the object in memory).
- In Case 1
id(x)
is not equal toid(y)
hencex is y
returnsFalse
. - In Case 2
id(x)
is equal toid(y)
which implies bothx
andy
refers to the same object inside the memory hencex is y
returnsTrue
.
Now coming to your question,
def foo(el):
return (el is 0.0)
In the function foo
el is 0.0
returns False
because each of the two entities el
and 0.0
refer to different locations inside memory. You can verify this fact by comparing id(el) == id(0.0)
which returns False
.
When, if ever, to use the 'is' keyword in Python?
You should use is
when you want to know whether two objects are the same object. Don't use it when you want to know whether two objects have the same value.
There is a canonical example, but it is unfortunately not very helpful. People will tell you to always test for the None
value using x is None
instead of x == None
. However, there is little practical difference between these cases. (See this question for explanation.)
In some situations, you may wind up creating objects which have the same value but are distinct objects. For instance, you could imagine creating a fantasy wargame in which the player can magically create minions to battle his opponent. So the player might create 100 identical orcs or whatever. Each orc could be represented by an object, and they would be identical in that they have the same properties, but still distinct in that there would be 100 separate objects. Now if the opponent tries to cast a "fireball" spell on one of these orcs, while on the same turn the player tries to cast "protect against fire" on an orc, you might want to check if the target of the fireball spell is
the target of the protection spell. Equality wouldn't be enough, because all the orcs are equal, but only one particular orc is the target of each spell, and you want to know if the two targets are the same object. This is a rather contrived example, but should give a broad idea of the kind of situation where you might wind up using is
.
Can I make my class play nice with the Python 'in keyword?
For iterating as in for x in object
, you need to provide an __iter__
method which will return a new iterator.
An iterator is an object which has a method next()
(Python 2) or __next__
(Python 3) which either returns the next element or raises StopIteration
exception when there are no more elements. (An iterator should also have a method __iter__
that returns itself.)
Tip: You don't often need to code an iterator by yourself; the simplest way to implement
__iter__
on a class is to make it agenerator function
or to return a generator expression from it (all generators are iterators). Also you can just return an iterator obtained from another object; theiter
builtin is helpful here.
For testing if x in object
, you need to provide a __contains__
method.
Further reading: Python data model - emulating container types
What is the python keyword with used for?
In python the with
keyword is used when working with unmanaged resources (like file streams). It is similar to the using
statement in VB.NET and C#. It allows you to ensure that a resource is "cleaned up" when the code that uses it finishes running, even if exceptions are thrown. It provides 'syntactic sugar' for try/finally
blocks.
From Python Docs:
The
with
statement clarifies code that previously would usetry...finally
blocks to ensure that clean-up code is executed. In this section, I’ll discuss the statement as it will commonly be used. In the next section, I’ll examine the implementation details and show how to write objects for use with this statement.The
with
statement is a control-flow structure whose basic structure is:with expression [as variable]:
with-blockThe expression is evaluated, and it should result in an object that supports the context management protocol (that is, has
__enter__()
and__exit__()
methods).
Update fixed VB callout per Scott Wisniewski's comment. I was indeed confusing with
with using
.
The built-in keyword type means a function or a class in python?
type
is called a "metaclass" because it's a class that produces other classes (AKA types). It behaves like a normal class. In particular, it has the equivalent of a __new__
method that would look something like this in Python:
class type(object):
def __new__(cls, *args):
num_args = len(args)
if num_args not in (1, 3):
raise TypeError('type() takes 1 or 3 arguments')
# type(x)
if num_args == 1:
return args[0].__class__
# type(name, bases, dict)
name, bases, attributes = args
bases = bases or (object,)
class Type(*bases):
pass
Type.__name__ = name
qualpath = Type.__qualname__.rsplit('.', 1)[0]
Type.__qualname__ = '.'.join((qualpath, name))
for name, value in attributes.items():
setattr(Type, name, value)
return Type
Class = type('Class', (), {'i': 1})
instance = Class()
print(type(instance)) # -> Class
print(instance.__class__) # -> Class
print(type(type(instance))) # -> type
print(Class.i) # -> 1
print(instance.i) # -> 1
Note that when instantiating a class, the value of the new instance is whatever is returned from __new__
. In the case of type
, __new__
always returns a type object (AKA class). Here's an example of a class that extends int
to use -1
as the default value instead of 0
:
def Int__new__(cls, *args):
if not args:
return cls(-1)
return super(cls, cls).__new__(cls, *args)
Int = type('Int', (int,), {'__new__': Int__new__})
i = Int()
print(type(i)) # -> Int
print(i.__class__) # -> Int
print(type(type(i))) # -> type
print(i) # -> -1
j = Int(1)
print(j) # -> 1
To really dig into how type
works, take a look at the C code in type_new
. You can see there (scroll down a few lines) that type(x)
is a special case that immediately returns the type (AKA class) of x
. When you do type(name, bases, dict)
, the type creation machinery is invoked.
For more fun, try the following:
type(object)
type(type)
isinstance(object, object)
isinstance(type, object)
type(1)
type(type(1))
Is 'input' a keyword in Python?
No, input
is not a keyword. Instead, it is a built-in function.
And yes, you can create a variable with the name input
. But please don't. Doing so is a bad practice because it overshadows the built-in (makes it unusable in the current scope).
If you must use the name input
, the convention is to place an underscore after it:
input_ = input()
Related Topics
Python Ta-Lib Install Error, How Solve It
Run a Linux System Command as a Superuser, Using a Python Script
Difference Between Variables Inside and Outside of _Init_()
How to Get the Input from the Tkinter Text Widget
Get List from Pandas Dataframe Column or Row
How to Install Python Modules Without Root Access
What Does Preceding a String Literal with "R" Mean
Making Python/Tkinter Label Widget Update
Postgresql: How to Install Plpythonu Extension
Importerror: Libcblas.So.3: Cannot Open Shared Object File: No Such File or Directory
Why Is a List Comprehension So Much Faster Than Appending to a List
How to "Test" Nonetype in Python
Add Leading Zeros to Strings in Pandas Dataframe
Passing Functions with Arguments to Another Function in Python