Python study notes - iterators and classes

iterator

There is a difference between iterators and iterables:

 list, truple, str, dict can all be iterated, but they are not iterators

Anything that can for loop is Iterable (iterable object), which implements the __iter__ method

Anything that can be next() is an Iterator

Iterators are iterable objects

An iterator has 2 elements:

__iter__(): Returns the iterator object itself. Called when an iterative object is generated, the return value must be the object itself, then for can call the next method in a loop

next(): This method is called every time the for loop (must exist)

Judging the iterable object

In [36]: from collections import Iterable

In [27]: L = [1,2]

In [28]: it = iter(L)

In [38]: isinstance(L,Iterable)

Out[38]: True

In [39]: isinstance(it,Iterable)

Out[39]: True

In [40]: isinstance(100,Iterable)

Out[40]: False

 

judge iterator

In [41]: from collections import Iterator

In [42]: isinstance(it,Iterator)

Out[42]: True

In [43]: isinstance({'name':'zhailiang','career':'devops'},Iterator)

Out[43]: False

In [44]: isinstance((x for x in range(10)),Iterator)

Out[44]: True

 

 

Iterator: Implement the next method and return StopIteration when there is no data to return

An iterator is a pointer, and iter() is a built-in function that produces an iterator over a sequence

In [20]: with open('/etc/passwd') as f: # File object provides iterator protocol

    ...: for line in f: # The for loop uses the iterator protocol to access the file

    ...:         print (line)

    ...:        

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

 

 

In [27]: L = [1,2]

In [28]: it = iter(L)

In [28]: it

Out[28]: <list_iterator at 0x7f93e0038cc0>

In [29]: next(it)

Out[29]: 1

In [30]: next(it)

Out[30]: 2

In [31]: L.append(3)

In [32]: next(it)

Out[32]: 3

In [33]: next(it)

StopIteration Traceback (most recent call last)

<ipython-input-33-bc1ab118995a> in <module>()

----> 1 next(it)

StopIteration:

See how many letters are on each line of the file:

In [4]: it = (len(x) for x in open('/app/big.txt'))

 

In [5]: it

Out[5]: <generator object <genexpr> at 0x7f34350fc0f8>

In [6]: type(it)

Out[6]: generator

 

In [7]: next(it)

Out[7]: 65

In [8]: next(it)

Out[8]: 26

 

The iterator is a one-time consumption, and it ends when it is used up. If called again, a StopIteration exception will be raised

Iterators can be saved using deepcopy from the copy package:

In [51]: import copy

In [49]: L

Out[49]: [1, 2, 3]

 

In [54]: I=iter(L)

In [55]: J=copy.deepcopy(I)

In [56]: next(I)

Out[56]: 1

 

In [57]: next(I)

Out[57]: 2

In [58]: next(I)

Out[58]: 3

In [59]: next(J)

Out[59]: 1

In [60]: next(J)

Out[60]: 2

generator function

Generator functions must remember three things:

1) Syntactically, change return to yield, and use the yield statement to return one result at a time,

Between each result, suspend and continue their state

2) In terms of implementation, the generator automatically implements the iterator protocol;

3) The generator will retain the state where the function left, so that the next call will continue from where it left off last time

Generator Expressions: Similar to list comprehensions, however, generators return an expression that produces results on demand

object instead of building a list of results one at a time

files are also generators

 

In [34]: def gensquares(N):

    ...:     for i in range(N):

    ...:         yield i**2

   In [35]: for item in gensquares(5):

    ...:     print (item),

0

1

4

9

16

 

In [41]: def d(n):

   ....:     for i in range(n):

   ....:         yield i

   ....:

In [42]: a=d(5)

In [43]: a.next()

Out[43]: 0

In [44]: a.next()

Out[44]: 1

In [45]: a.next()

Out[45]: 2

 

In [46]: for i in a:print i

3

4

 

Generator induction:

  1. The generator is the same as the regular function. When the generator is created, the iterator protocol will be automatically implemented so that it can be applied to the iterative background (such as for loop). When this function is called, the code inside the function is not executed immediately. This The function just returns a generator object. When using for to iterate, the code inside the function is executed.
  2. State suspension: In a function, when the program executes to the yield statement, the program pauses, returns the value of the expression following the yield, maintains the state, and jumps out of the loop
  3. The generator object implements the iterator protocol (automatically implemented), its __next__ method can be called, and when there is no value to return, a StopIteration exception is generated
  4. A generator is actually a special kind of iterator

On the next call, continue execution from where the yield statement left off, and so on until the function finishes executing.

 

But in python3.X, the next in generator (functions with the yield keyword will be recognized as generator functions) has become __next__, and next is a method in previous versions of python 3.x:

In [67]: a = (x*x for x in range(10))

In [68]: a.__next__()

Out[68]: 0

In [69]: a.__next__()

Out[69]: 1

This is the implementation of Fibonacci:

[root@localhost python_practice]# cat yiel_1.py

#!/usr/bin/python

def fib(max): 

    a, b = 1, 1 

    while a < max: 

        yield a 

        a, b = b, a+b 

for n in fib(10): 

print n 

 

tips:

a, b = b, a+b is equivalent to

t = (b, a + b) # t is a tuple

a = t[0]

b = t[1]

When max=10, enter the fib() generator, execute to yield a, return the value of a and the state of the entire generator pause (return an iterator object containing the state of all parameters of the current function), assign the value of a to n, Print it out; because it is a for statement loop, it returns to the fib(10) statement. Since it is a generator, it starts executing from the last truncated position, and the b value is assigned to a, and the a+b value is assigned to b, and because If it is a while statement, continue the while loop, yield a value, pause the loop and jump out to return the a value and the generator state, assign the a value to n, and print n. This goes back and forth until the end of 10.

The role of yield is to turn a function into a generator

On the next iteration, the code continues execution from the next statement of yield a

The whole process is as follows:

                       

[root@localhost python_practice]# python yiel_1.py

1

1

2

3

5

8

In [69]: f = fib(10)

In [70]: print('fib(10):', f)

fib(10): <generator object fib at 0x7fad25442f68>

 

 

Use a fixed-length buffer to continuously read the contents of the file:

def readfile(fpath):           

    with open(fpath) as f: 

        while True: 

            buf = f.read(1024) 

            if buf: 

                yield buf 

            else: 

                return 

 

for i in readfile("about.html"): 

print i,

 

8 Classes and Objects

10.1 Basics

Objects can use ordinary variables that belong to objects to store data. Variables belonging to an object or class are called domains. Objects can also have functionality using functions belonging to a class. Such functions are called methods of the class. These terms help us distinguish them from isolated functions and variables. Fields and methods can be collectively called properties of a class.

Domains are of two types - objects that belong to each instance/class or belong to the class itself. They are called instance variables and class variables, respectively.

Classes are created using the class keyword. The fields and methods of a class are listed in an indented block.

Creation process:

1. Instance Creation - Populate Instance Properties

2. Behavioral methods - encapsulate logic in class methods

3. Operator overloading - provides behavior for printing built-in operations

4. Custom behavior - create subclasses to make them special

5. Custom constructor - adding initialization logic to the superclass

[root@shanghai-WEB-228-102_nginx ~]# cat class.py

#!/usr/bin/python

class Person:

        pass # an empty block

p=Person()

print p

[root@shanghai-WEB-228-102_nginx ~]# python class.py

<__main__.Person instance at 0x7f901261fef0>

This is a space in memory where the computer memory address where the object is stored is also printed. This address will be a different value on different servers, because Python can store objects in any slot.

Object methods:

[root@shanghai-WEB-228-102_nginx ~]# cat method.py

#!/usr/bin/python

#filename:method.py

class Person:

        def sayhi(self):

                name=raw_input('enter input your name:')

                print 'hello %s,how are you?' % name

p=Person()

p.sayhi()

[root@shanghai-WEB-228-102_nginx ~]# python method.py

enter input your name:kingleoric

hello kingleoric,how are you?

self refers to the class instance object itself (note: not the class itself).

__init__method

The __init__ method runs as soon as an object of the class is created. This method can be used to initialize your object as you wish. Note that the name begins and ends with double underscores.

[root@shanghai-WEB-228-102_nginx ~]# cat class_init.py

#!/usr/bin/python

#filename:class_init.py

class Person:

        def __init__(self,name):

                self.name=name

        def sayhi(self):

                print 'hello, my name is',self.name

p=Person('kingleoric')

p.sayhi()

[root@shanghai-WEB-228-102_nginx ~]# python class_init.py

hello, my name is kingleoric

 

methods of classes and objects

Now let's look at the data part of classes and objects. They are just ordinary variables bound to the namespaces of classes and objects, i.e. these names are only valid under the premise of those classes and objects.

There are two types of domains - variables of a class and variables of an object, and they are distinguished according to whether the class or the object owns the variable.

Class variables are shared by all objects (instances) of a class. There is only one copy of a class variable, so when an object makes a change to a class variable, the change is reflected on all other instances.

The variables of an object are owned by each object/instance of the class. Therefore each object has its own copy of this field, that is, they are not shared, and in different instances of the same class, although the variables of the object have the same name, they are not related to each other.

 

[root@shanghai-WEB-228-102_nginx ~]# vi objvar.py

#!/usr/bin/python

#filename:objvar.py

class Person:

        population=0

        def __init__(self,name):

                self.name=name

                print '(initializing %s)' %self.name

                Person.population+=1

        def __del__(self):

                print '%s say bye.' %self.name

                Person.population-=1

                if Person.population==0:

                        print 'I am the last one'

                else:

                        print 'there are still %d people left' %Person.population

        def sayhi(self):

                print 'hi,my name is %s.' %self.name

        def howmany(self):

                if Person.population==1:

                        print 'I am the only person here.'

                else:

                        print 'we have %d persons here.' %Person.population

kingleoric=Person('kingleoric')

kingleoric.sayhi()

kingleoric.howmany()

 

leon=Person('leon liang')

leon.sayhi()

leon.howmany()

 

kingleoric.sayhi()

kingleoric.howmany()

[root@shanghai-WEB-228-102_nginx ~]# python objvar.py

(initializing kingleoric)

hi,my name is kingleoric.

I am the only person here.

(initializing leon liang)

hi,my name is leon liang.

we have 2 persons here.

hi,my name is kingleoric.

we have 2 persons here.

leon liang say bye.

there are still 1 people left

kingleoric say bye.

Exception AttributeError: "'NoneType' object has no attribute 'population'" in <bound method Person.__del__ of <__main__.Person instance at 0x7fa85969c440>> ignored

 

After modification:

[root@shanghai-WEB-228-102_nginx ~]# cat objvar2.py

#!/usr/bin/env python

# Filename: objvar.py

 

class Person:

        '''Represents a person.'''

        population=0

 

        def __init__(self,name):

                '''Initializes the person's data.'''

                self.name=name

                print '(Initializing %s)' %self.name

 

                #When this person is created, he/she adds to the population

                Person.population+=1

 

        def __del__(self):

                '''I am dying.'''

                print '%s says bye.' %self.name

 

                Person.population-=1

 

                if Person.population==0:

                        print 'I am the last one.'

                else:

                        print 'There are still %d people left.' %Person.population

 

        def sayHi(self):

                '''Greeting by the person.

 

                Really, that's all it does.'''

                print 'Hi, my name is %s.' %self.name

 

        def howMany(self):

                '''Prints the current population.'''

                if Person.population==1:

                        print 'I am the only person here.'

                else:

                        print 'We have %d persons here.' %Person.population

 

swaroop=Person('kingleoric')

swaroop.sayHi()

swaroop.howMany()

 

kalam = Person ('Abdul kalam')

kalam.sayHi()

kalam.howMany()

 

swaroop.sayHi()

swaroop.howMany()

[root@shanghai-WEB-228-102_nginx ~]# python objvar2.py

(Initializing kingleoric)

Hi, my name is kingleoric.

I am the only person here.

(Initializing Abdul kalam)

Hi, my name is Abdul kalam.

We have 2 persons here.

Hi, my name is kingleoric.

We have 2 persons here.

Abdul kalam says bye.

There are still 1 people left.

kingleoric says bye.

I am the last one.

Parse:

__init__The method initializes the Personinstance with a name. In this method, we let populationincrease 1because we added a person. It can also be found that self.namethe value of , is specified on a per-object basis, indicating its nature as a variable of an object.

 

 

Call other methods in the class:

    def get_avg(self):

        return self.get_score() / 3

The whole code is:

#!usr/bin/python

class Student:

    def __init__(self, name, chinese=0, english=0, math=0):

        self.name = name

        self.english = english

        self.math = math

        self.chinese = chinese

    def get_name(self):

        return self.name

    def get_score(self):

        return self.chinese + self.english + self.math

    def get_avg(self):

        return self.get_score() / 3

if __name__ == '__main__':

    bob = Student('bob', 100, 85, 96)

    print bob.get_name(), bob.get_score(), bob.get_avg()

   

result

/usr/local/bin/python2.7 /root/PycharmProjects/spider/student_class.py

bob 281 93

__init__ and __new__

__new__() is to create a class instance object, and __init__ is called after the class instance is created.

The singleton pattern of the design pattern can be realized by using the characteristics of this method and the properties of the class. The singleton pattern refers to the creation of unique objects, and the classes designed in the singleton pattern can only be instanced

1.__new__ is a static method, while __init__ is an instance method.

2. The __new__ method returns a created instance, while __init__ returns nothing.

3. The following __init__ can only be called when __new__ returns an instance of cls.

4. Call __new__ when creating a new instance, and use __init__ when initializing an instance.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324755256&siteId=291194637