Not Just Paranoid

Another site by Pete Maynard

Python Learning

Random Talk

Python3

Data Structures

Data types which return False, anything which is not in this list will return ture. So for example -1 will return True.

	''
	None
	[]
	()
	0
	False

To specify an empty body use pass

	if a<b: 
		pass
	else: 
		print('beep')

Python is strong, dynamically typed. Meaning that a variable will not change it’s type without explicitly being stated. That being said the following is perfectly valid.

	a_variable = 1
	a_variable = "I am a string"

Because the variable does not have a type.

Pythons operators will only accept compatible types. Otherwise it will raise a type error.

	no1 = 1
	no1 + 1234
	try:
	    print(no1 + "abc")
	except TypeError as e:
	    print("Dynamic typing means '+' wont work with mismatched types")

Python everything is an Object. Nothing is a value type, only reference type.

	ref = print 
	print(ref)
	<built-in function print>

Duck typing Python accepts any object as a function argument. If it walks and talks like a Duck, it’s a Duck.

	class MyFoo():
		def foo(self):
			print('Bar')

	class MyBar():
		def bar(self):
			print("Foo")

	def callFoo(func):
		func.foo()

	try:
		mf = MyFoo()
		mb = MyBar()
		callFoo(mf)
		callFoo(mb)
	except AttributeError as e:
		print("Missing Attribute/Method.")

Loops

enumerate(iterable, start=0)

Takes a compatible type, sequence, and returns an iterator (ID:Value). Also see Iterator

	for pair in enumerate([10,20,50,80,40,100]]):
	    print('Value at index %d is %s' % (pair[0], pair[1]))

while supports the else clause. It will only be called when ‘break’ is not used.

Sequences

List (mutable), Tuple (immutable), strings and maps

	tuple = (a,b,c)

Tuple is an immutable list. See List comprehension

Functions

Functions with many arguments, you can use def manyArguments(name, *args): Put all remaining parameter in a tuple sequence.

	def manyArguments(name, *args):
		print("Hey %s\nOther arguments:" % name)
		for arg in args:
			print("\t%s" % arg)

	manyArguments("pigeon", 1, 5, 5.0)

Functions can be given in any order if specified as func(b=12, a='ab', x=99, y='zz')

Regex

Don’t use re.match unless you want to match strings only at the beginning.

A match object is returned on success, otherwise None, it’s boolean True. It is better to use a match object where you can.

	iterator = re.finditer('(pig)([a-z]{3})', "beep pigeon troll")
	for match in iterator:
	    print("Full match (%s) \nGroup 1 (%s) \nGroup 2 (%s)" \
	          % (match.group(0), match.group(1), match.group(2)))

re.sub can take a function as replacement value.

	def myFunc(match):
		return match.group(0).lower()

	subResult = re.sub('PIGEON', myFunc, "BEEP PIGEON TRoLL")
	print(subResult)

lambda

Unnamed function, a function which is a self contained block of code which can be used as a parameter. Restricted to just one line.

	lambda a,b: a + b

Example as above:

	subResult = re.sub('PIGEON', lambda m: m.group(0).lower(), "BEEP PIGEON TRoLL")
	print(subResult)

Functional Programming

Built-in Python.

Reverse

Quick python hack to reverse words. Start at the default 0, end at the default len(str), set the stepping point to -1.

[start : ending : stepping char]

	print("forwards"[::-1])

List comprehension

Some examples, reduce the amount of loops a clearer simpler syntax. Do it imminently.

Object Oriented Programming

Important to note that the number of fields a class can have may not be constant. When writing a class it’s a good idea to override _str_ and _repr_ methods. Repr is used to return a formal machine readable version of the class used for serialization. It’s not possible to have private fields, it’s a scripting language, it’s not designed for big projects. (See Larry Wall on privacy- shotgun). Although you can add __ (underscore, underscore) to a field name, which will mangle it. This can help prevent potential shadowing and accidental use. Though it won’t stop bad people from doing bad things.

With

If a class uses _enter_ and _exit_ you can use with. This is used for IO and network to close and open file descriptors.

	class Pigeon: 
		def __enter__(self):
			print("Starting the pigeon drive... ", end='')

		def activate(self):
			print("Activated. ", end='')

		def __exit__(self, xc_type, exc_val, exc_tb):
			print("Power down complete!")
				
	pig = Pigeon()
	with pig:
		pig.activate()

Decorators

‘@’ are used as a decorator. It is attached to a class or method. It can declare properties and static methods.

Static Fields

Good for database connections. Accessed via every instance of class.

	class Pigeon:
	    numPigeons = 0
	    def __init__(self):
	    	Pigeon.numPigeons += 1 

Static method. Declared in the class but does not become part of the new instance. Static methods live at the level of the class. Note that there is no ‘self’, so no current object/instance.

	class Pigeon:
		numPigeons = 0
		def __init__(self):
			Pigeon.numPigeons += 1 

		@staticmethod
		def print_pigeons():
			print(Pigeon.numPigeons)

	p1 = Pigeon()
	p2 = Pigeon()

	Pigeon.print_pigeons()

Custom Decorator

	def my_decorator(func):
		def my_wrapper(*args):
			print("Replacing '%s' with 'Pigeon'" % args[0])
			func('Pigeon', args[1])
		return my_wrapper

	@my_decorator
	def foo(a, b):
		print('Foo called with %s and %s' % (a, b))

	foo('Cat', 'Dog')

my_decorator must accept return a function. This function (my_wrapper) will now be invoked instead of Foo.

This allows arbitrary functions to be called as a wrapper for functions. For example you can add @log, which could log when and what arguments the function was called with. This is called Aspect Oriented Programming (AOP), aspects change over time. More examples of decorators are Thread safety, auditing and security i.e user permissions.

Properties

Decorators are used to specify properties. Properties look like a field but acts like a method.

	class Pigeon:
		def __init__(self, numb):
			self.numbPigeons = numb
		def __str__(self):
			return str(self.numbPigeons)

		@property
		def count(self):
		    return self.numbPigeons

		@count.setter
		def count(self, value):
		    self.numbPigeons = value

		@count.deleter
		def count(self):
			self.numbPigeons = -1
			# raise TypeError("Pigeons do not talk")

	p = Pigeon(1)
	print(p)
	p.count = 10
	print(p)
	del p.count
	print(p)

Iterator

To create your own iterator object you need to have the _iter_ and _next_ method. At the end simply raise StopIteration See docs

	class PigeonIterator:
	    def __init__(self, input):
	        self.data = input
	        self.index = 0

	    def __iter__(self):
	        return self

	    def __next__(self):
	        if self.index == len(self.data):
	            raise StopIteration
	        else:
	            retn = self.data[self.index]
	            self.index += 1
	            return retn

	for pigeon in PigeonIterator(("Aachen Cropper", "Baja Tumbler", "Beak-Crested Jacobin")):
	    print(pigeon)

Reflection/Introspection

Meta classes, a class which holds the details of another class.

	k = PigeonClass.__class__
	for name in k.__dict__:
		print('\t\t%s' % name)

Testing

Any class inherited from unittest and a method which starts with test.

	import unittest

	class PigeonTest(unittest.TestCase):
	    def setUp(self):
	        self.pigeonObj = Pigeon(12)
	    
	    def tearDown(self):
	        pass
	        
	    def test_count(self):
	        self.assertEqual(12,self.pigeonObj.count)

	    def test_set(self):
	    	self.pigeonObj.count = 9999999999999
	    	self.assertEqual(9999999999999,self.pigeonObj.count)

	    def test_del(self):
	    	del self.pigeonObj.count
	    	self.assertEqual(-1,self.pigeonObj.count)

	if __name__ == '__main__':
	    unittest.main()

Generator

Unlike list comprehension, generators only generates a value wen you say next they are lazy.

g = generator() Is a link to live function, it will not return anything until next is called on it. Usefull for making queries to a database to prevent 100 calls as soon as the script is loaded.

It returns a StopIteration when it is finished.

	def generate(number, power):
	    print('Raising %d to the power of %d' %(number, power))
	    retval = 1
	    for x in range(power):
	        retval *= number
	        yield retval
	    return
	        
	g = generate(4, 5)
	print('%5d' % next(g))
	print('%5d' % next(g))
	print('%5d' % next(g))
	print('%5d' % next(g))
	print('%5d' % next(g))

	try:
	   next(g)
	except StopIteration as ex:
	    print('Whoops - generator has completed!')
	    
	myList = list(generate(5, 4))
	for item in myList:
	    print('%5d' % item)

Inside generator we yield and return a value.

Shorthand/simpler - Generator expression

	g = (c * 2 for c in 'python')

16 Apr 2014 | Tags ( python )

Website Last Updated on 15 Sep 2023 (CC BY-SA 4.0)

This site uses JQuery and nanogallery2 hosted by jsdelivr.net
for the Flickr photo feed and GoatCounter for user insights.