笔记-python tutorial-9.classes

笔记-python tutorial-9.classes

1.      Classes

1.1.    scopes and namespaces

namespace: A namespace is a mapping from names to objects.

典型的命名空间有:built-in names;the global names in a module; the local names in a function.

两个命名空间中的名称之间没有任何关系,例如两个模块可以都定义一个函数func1(),但在使用时需要加上模块名做前缀以示区别。

属性是只读或可写的。

namespaces are created at different moments and have different lifetimes. The namespace containing the built-in names is created when the Python interpreter starts up, and is never deleted.

The global namespace for a module is created when the module definition is read in; normally, module namespaces also last until the interpreter quits. 

The statements executed by the top-level invocation of the interpreter, either read from a script file or interactively, are considered part of a module called __main__, so they have their own global namespace. (The built-in names actually also live in a module; this is called builtins.)

The local namespace for a function is created when the function is called, and deleted when the function returns or raises an exception that is not handled within the function. (Actually, forgetting would be a better way to describe what actually happens.) Of course, recursive invocations each have their own local namespace.

scope:A scope is a textual region of a Python program where a namespace is directly accessible. “Directly accessible” here means that an unqualified reference to a name attempts to find the name in the namespace.

Although scopes are determined statically, they are used dynamically. At any time during execution, there are at least three nested scopes whose namespaces are directly accessible:

  • the innermost scope, which is searched first, contains the local names
  • the scopes of any enclosing functions, which are searched starting with the nearest enclosing scope, contains non-local, but also non-global names
  • the next-to-last scope contains the current module’s global names
  • the outermost scope (searched last) is the namespace containing built-in names

如果名字声明为全局,则所有声明为global的名称均为同一个,有点绕,效果见下面的测试。

# 奇怪的测试

def fun1():

    num = 5

    def fun2():

        global num

        num = 6

        print('fun2',num)

        def fun3():

            num = 7

            print('fun3',num)

            def fun4():

                global num

                print('fun4',num)

            fun4()

        fun3()

    fun2()

fun1()

输出:

fun2 6

fun3 7

fun4 6

A special quirk of Python is that – if no global statement is in effect – assignments to names always go into the innermost scope. Assignments do not copy data — they just bind names to objects. The same is true for deletions: the statement del x removes the binding of x from the namespace referenced by the local scope. In fact, all operations that introduce new names use the local scope: in particular, importstatements and function definitions bind the module or function name in the local scope.

这段不是很明白具体的意思。不过下面的代码会报错。

# 奇怪的测试

# 奇怪的测试

def fun1():

    num = 5

   

    def fun2():

        #global num

        num = 6

        print('fun2',num)

        def fun3():

            num = 7

            print('fun3',num)

            def fun4():

                global num

                #num = 9

                print('fun4',num)

            fun4()

        fun3()

    fun2()

fun1()

print(num)

报错显示在fun4()中name ‘num’ is not defined,但去掉任何一个或两个#号都可以正常运行。

1.1.1.   scopes and namespaces example

下面是一段效果演示代码:

def scope_test():

    def do_local():

        spam = "local spam"

    def do_nonlocal():

        nonlocal spam

        spam = "nonlocal spam"

    def do_global():

        global spam

        spam = "global spam"

    spam = "test spam"

    do_local()

    print("After local assignment:", spam)

    do_nonlocal()

    print("After nonlocal assignment:", spam)

    do_global()

    print("After global assignment:", spam)

scope_test()

print("In global scope:", spam)

输出:

After local assignment: test spam

After nonlocal assignment: nonlocal spam

After global assignment: nonlocal spam

In global scope: global spam

1.2.    类基础介绍

1.2.1.   class definition syntax

class ClassName():

       <statement-1>

       ……

1.2.2.   class objects

class objects support two kinds of operations:attribute reference and instantiation.

1.2.3.   instance objects

there are two kinds of valid atribute names, data attributes and methods.

data attributes correspond to “instance variables” in Smalltalk, and to “data members” in C++. Data attributes need not be declared; like local variables, they spring into existence when they are first assigned to. 

A method is a function that “belongs to” an object.

method可以通过以下方式引用:

x.f()

实例方法调用时实例对象作为函数的第一个参数传递。

1.2.4.   class and instance variables

class Dog:

    kind = 'canine'         # class variable shared by all instances

    def __init__(self, name):

        self.name = name    # instance variable unique to each instance

>>> d = Dog('Fido')

>>> e = Dog('Buddy')

>>> d.kind                  # shared by all dogs

'canine'

>>> e.kind                  # shared by all dogs

'canine'

>>> d.name                  # unique to d

'Fido'

>>> e.name                  # unique to e

'Buddy'

一般而言,实例变量用于保存实例数据,而类变量可以被整个类的实例共享。

一般情况下类变量不使用可变类型。

1.3.    类的继承

派生类定义:

class DerivedClassName(BaseClassName):

    <statement-1>

    .

    .

    .

    <statement-N>

基类名必需是对定义语句可访问的,对于不同模块中的类继承可以使用以下方式;

class DerivedClassName(modname.BaseClassName):

构造类对象时,会记住基类。如果在类中找不到属性,则向上递归在基类中寻找。

Python中有两个内置函数用于查看继承类:

isinstance(obj, int):检查是否某一类

issubclass(bool, int):检查是否为某类的子类

1.3.1.   多继承

python支持多继承

class DerivedClassName(Base1, Base2, Base3):

    <statement-1>

    .

    .

    .

    <statement-N>

大多数情况下,在父类中查找属性的顺序是深度优先,从左至右,如果在层次结构中有重叠也不会搜索两次。

python支持super(),这一机制在其它语言中叫做call-next-method。

因为多继承都会表现出一个或多个菱形拓扑关系图,为防止基类被多次访问,动态算法保证只调用每个父类一次。

1.4.    private variables私有变量

python中并不存在真正的“私有”变量,但是,多数代码都遵守一个约定,以_为前缀的名称是api的非公共部分(包括函数,方法或数据成员)。

class Mapping:

    def __init__(self, iterable):

        self.items_list = []

        self.__update(iterable)

    def update(self, iterable):

        for item in iterable:

            self.items_list.append(item)

    __update = update   # private copy of original update() method

class MappingSubclass(Mapping):

    def update(self, keys, values):

        # provides new signature for update()

        # but does not break __init__()

        for item in zip(keys, values):

            self.items_list.append(item)

1.5.    iterators迭代实现

for语句实际上使用了迭代来实现,__next__()一次抛出一个元素,没有更多元素时,__next__()抛出一个StopIteration异常告诉for终止循环。

也可以使用内建函数next()自己调用__next__()方法

>>> s = 'abc'

>>> it = iter(s)

>>> it

<iterator object at 0x00A1DB50>

>>> next(it)

'a'

>>> next(it)

'b'

>>> next(it)

'c'

>>> next(it)

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

    next(it)

StopIteration

下面是一个自定义附有迭代功能的类定义代码:

class Reverse:

    """Iterator for looping over a sequence backwards."""

    def __init__(self, data):

        self.data = data

        self.index = len(data)

    def __iter__(self):

        return self

    def __next__(self):

        if self.index == 0:

            raise StopIteration

        self.index = self.index - 1

        return self.data[self.index]

>>> rev = Reverse('spam')

>>> iter(rev)

<__main__.Reverse object at 0x00A1DB50>

>>> for char in rev:

...     print(char)

...

m

a

p

s

1.6.    generators

生成器是创建迭代器的工具,写起来很像正常的语句,但当要返回值时使用yield语句。每一次next()调用它时,生成器记住它离开的位置(包括数据和最后一个语句)。

下面是一个生成器示例:

def reverse(data):

    for index in range(len(data)-1, -1, -1):

        yield data[index]

>>> for char in reverse('golf'):

...     print(char)

...

f

l

o

g

当生成器终止时,自动抛出StopIteration异常。

1.7.    generator expressions

一些简单的生成器可以使用类似于列表推导式的语法,但需要使用括号而不是方括号。这些表达式一般用于立即生成数据,生成器表达式比完整的的生成器定义更简洁但功能更少,而且往往比等效的列表推导占用更少内存。

示例:

>>> sum(i*i for i in range(10))                 # sum of squares

285

>>> xvec = [10, 20, 30]

>>> yvec = [7, 5, 3]

>>> sum(x*y for x,y in zip(xvec, yvec))         # dot product

260

>>> from math import pi, sin

>>> sine_table = {x: sin(x*pi/180) for x in range(0, 91)}

>>> unique_words = set(word  for line in page  for word in line.split())

>>> valedictorian = max((student.gpa, student.name) for student in graduates)

>>> data = 'golf'

>>> list(data[i] for i in range(len(data)-1, -1, -1))

['f', 'l', 'o', 'g']

猜你喜欢

转载自www.cnblogs.com/wodeboke-y/p/9718006.html
今日推荐