02Python学习笔记之二.五【作用域、动态添加属性方法、types.MethodType、slots】2019-08-18

章节号 内容            
1图片格式(png) 宽度大于620px,保持高宽比减低为620px
1-1 应用
1-1-1 方法

第1章节  作用域

improt 库
#使用库内的对象
库.XXXXX
from 库 import *
#使用库内的对象,直接使用
XXXXX

  1、局部变量:在函数或方法内定义的变量globals()
  2、全局变量:在函数或方法外定义的变量locals()

In [1]: globals()
Out[1]: 
{'In': ['', 'globals()'],
 'Out': {},
 '_': '',
 '__': '',
 '___': '',
 '__builtin__': ,
 '__builtins__': ,
 '__doc__': 'Automatically created module for IPython interactive environment',
 '__loader__': None,
 '__name__': '__main__',
 '__package__': None,
 '__spec__': None,
 '_dh': ['/home/li'],
 '_i': '',
 '_i1': 'globals()',
 '_ih': ['', 'globals()'],
 '_ii': '',
 '_iii': '',
 '_oh': {},
 '_sh': ,
 'exit': ,
 'get_ipython': >,
 'quit': }

  ↑当前环境可用的所有全局变量。这个操作会显示之前使用过的一些变量,建议先退出一次再进入ipython查看。

In [2]: locals()
Out[2]: 
{'In': ['', 'globals()', 'locals()'],
 'Out': {1: {...}},
 '_': {...},
 '_1': {...},
 '__': '',
 '___': '',
 '__builtin__': ,
 '__builtins__': ,
 '__doc__': 'Automatically created module for IPython interactive environment',
 '__loader__': None,
 '__name__': '__main__',
 '__package__': None,
 '__spec__': None,
 '_dh': ['/home/li'],
 '_i': 'globals()',
 '_i1': 'globals()',
 '_i2': 'locals()',
 '_ih': ['', 'globals()', 'locals()'],
 '_ii': '',
 '_iii': '',
 '_oh': {1: {...}},
 '_sh': ,
 'exit': ,
 'get_ipython': >,
 'quit': }

  ↑当前环境可用的所有局部变量

In [3]: def fun():
   ...:     a=110
   ...:     print(locals())
   ...:     

In [4]: fun()
{'a': 110}

  ↑使用这个函数来显示fun()的所有局部变量。VScode中也能用。
  全局和局部,同名如何找:
  1、先找局部变量,即自己本域。
  2、再看是不是闭包,是闭包找外一域中有没有。
  3、再找全局环境看有没有。
  4、再找语言内建环境
  报错!

num=100
def test1():
    num=200
    def test2():
        num=300
        print(num)
    return test2

test1()()
300
num=100
def test1():
    num=200
    def test2():
        #num=300
        print(num)
    return test2

test1()()
200
num=100
def test1():
    #num=200
    def test2():
        #num=300
        print(num)
    return test2

test1()()
100

  LEGB规则:
  1、Locals
  2、Enclosing
  3、Globals
  4、Builtins

In [5]: dir(__builtin__)
Out[5]: 
['ArithmeticError',
 'AssertionError',
 'AttributeError',
 'BaseException',
 'BlockingIOError',
 'BrokenPipeError',
 'BufferError',
 'BytesWarning',
 'ChildProcessError',
 'ConnectionAbortedError',
 'ConnectionError',
 'ConnectionRefusedError',
 'ConnectionResetError',
 'DeprecationWarning',
 'EOFError',
 'Ellipsis',
 'EnvironmentError',
 'Exception',
 'False',
 'FileExistsError',
 'FileNotFoundError',
 'FloatingPointError',
 'FutureWarning',
 'GeneratorExit',
 'IOError',
 'ImportError',
 'ImportWarning',
 'IndentationError',
 'IndexError',
 'InterruptedError',
 'IsADirectoryError',
 'KeyError',
 'KeyboardInterrupt',
 'LookupError',
 'MemoryError',
 'ModuleNotFoundError',
 'NameError',
 'None',
 'NotADirectoryError',
 'NotImplemented',
 'NotImplementedError',
 'OSError',
 'OverflowError',
 'PendingDeprecationWarning',
 'PermissionError',
 'ProcessLookupError',
 'RecursionError',
 'ReferenceError',
 'ResourceWarning',
 'RuntimeError',
 'RuntimeWarning',
 'StopAsyncIteration',
 'StopIteration',
 'SyntaxError',
 'SyntaxWarning',
 'SystemError',
 'SystemExit',
 'TabError',
 'TimeoutError',
 'True',
 'TypeError',
 'UnboundLocalError',
 'UnicodeDecodeError',
 'UnicodeEncodeError',
 'UnicodeError',
 'UnicodeTranslateError',
 'UnicodeWarning',
 'UserWarning',
 'ValueError',
 'Warning',
 'ZeroDivisionError',
 '__IPYTHON__',
 '__build_class__',
 '__debug__',
 '__doc__',
 '__import__',
 '__loader__',
 '__name__',
 '__package__',
 '__spec__',
 'abs',
 'all',
 'any',
 'ascii',
 'bin',
 'bool',
 'bytearray',
 'bytes',
 'callable',
 'chr',
 'classmethod',
 'compile',
 'complex',
 'copyright',
 'credits',
 'delattr',
 'dict',
 'dir',
 'display',
 'divmod',
 'dreload',
 'enumerate',
 'eval',
 'exec',
 'filter',
 'float',
 'format',
 'frozenset',
 'get_ipython',
 'getattr',
 'globals',
 'hasattr',
 'hash',
 'help',
 'hex',
 'id',
 'input',
 'int',
 'isinstance',
 'issubclass',
 'iter',
 'len',
 'license',
 'list',
 'locals',
 'map',
 'max',
 'memoryview',
 'min',
 'next',
 'object',
 'oct',
 'open',
 'ord',
 'pow',
 'print',
 'property',
 'range',
 'repr',
 'reversed',
 'round',
 'set',
 'setattr',
 'slice',
 'sorted',
 'staticmethod',
 'str',
 'sum',
 'super',
 'tuple',
 'type',
 'vars',
 'zip']

In [6]: 

第2章节  Python是动态语言

  静态语言是:运行之前要先编译的语言。
  动态语言可以:

In [7]: class cla(object):
   ...:     pass
   ...: 

In [8]: c=cla()

In [9]: dir(c)
Out[9]: 
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__']
In [10]: c.a=123

In [11]: dir(c)
Out[11]: 
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'a']

In [12]: 

  ↑定义的时候没有,运行的时候来添加一个a属性。

  • 2-1 Python是动态语言—添加属性

class cla(object):
    def __init__(self, name, age):
      self.name = name
      self.age = age

c=cla("zhangsan",40)
print(c.name)
print(c.age)

#动态给c添加一个addr,但是不影响其他的对象
c.addr="AAAAAAAAAAAAAAAAA"
print(c.addr)

#动态给cla类添加一个num,其他所有对象都可以使用
cla.num=0
print(c.num)

  ↑给类加,大家都可以用。
  ↑给对象加,自己用。

  • 2-2 Python是动态语言—添加方法

class cla(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def prii(self):
        print("pri")

def f1(self):
    print("f1")

c = cla("zhangsan", 40)

c.prii()

c.f1=f1
c.f1()

  1、在类外定义一个函数,填入一个形式参数。
  2、定义一个对象变量,把函数的引用传给这个变量
  3、使用变量()来调用函数
  注意:这样做,系统不会把对象当做参数传入给外部的这个函数,会报错。

02Python学习笔记之二.五【作用域、动态添加属性方法、types.MethodType、slots】2019-08-18_第1张图片

  ↓解决问题使用到的模块和方法

In [12]: import types

In [13]: types.MethodType
Out[13]: method

In [14]: help(types.MethodType)

Help on class method in module builtins:

class method(object)
 |  method(function, instance)
 |  
 |  Create a bound instance method object.
 |  
 |  Methods defined here:
 |  
 |  __call__(self, /, *args, **kwargs)
 |      Call self as a function.
 |  
 |  __delattr__(self, name, /)
 |      Implement delattr(self, name).
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __get__(self, instance, owner, /)
 |      Return an attribute of instance, which is of type owner.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __hash__(self, /)
 |      Return hash(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __lt__(self, value, /)
 |      Return self

  ↓改为:

import types
class cla(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def prii(self):
        print("pri")

def f1(self):
    print("f1")

c = cla("zhangsan", 40)

c.prii()

c.f1=types.MethodType(f1,c)

c.f1()
pri
f1

第3章节  types.MethodType的作用

  • 3-1 types.MethodType的作用—添加实例方法

import types

class cla(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def prii(self):
        print("pri")

def f1(self):
    print("f1")

c = cla("zhangsan", 40)

c.prii()

c.f1=types.MethodType(f1,c)

c.f1()

xxx=types.MethodType(f1,c)

xxx()
pri
f1
f1

  ↑可以看到,xxx()一样可以正常的执行。所以这个动态添加的办法和原生的属性还是有所区别的。执行了types.MethodType(f1,c)之后,相当于产生了一个特殊返回值,这个返回值指向的f1的函数代码,里面已经被默认传递了c对象作为参数,只要使用这个返回值,就可以当做是调用了对象的方法。
  c.f1=types.MethodType(f1,c)这么写之后,再调用c.f1(),完全是为了字面上的符合,符合这个操作的原意而已。

  • 3-2 types.MethodType的作用—添加静态方法(未学)

  在使用静态方法时,类中的self将不会再进行传值,此时,静态方法已经和类没什么关系了。
  需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数。

import types

class cla(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def prii(self):
        print("pri")

def f1(self):
    print("f1")

#@符号,要想起装饰器!
@staticmethod
def test():
    print(":static")

c = cla("zhangsan", 40)

#这里不也不是必须叫cla.test,随便都可以
cla.test=test
cla.test()
:static

  ↑这里不需要绑定,因为静态方法不需要任何的参数,只要赋值了就直接用。注意要使用类名来调用。

  • 3-3 types.MethodType的作用—添加类方法

import types

class cla(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def prii(self):
        print("pri")

def f1(self):
    print("f1")

@staticmethod
def test():
    print(":static")

@classmethod
def clsm(cls):
    print("classmethod call")

c = cla("zhangsan", 40)

cla.clsm=clsm

cla.clsm()
classmethod call

  ↑类方法也是直接赋值调用就行。

  动态添加可以做到什么呢?一款APP,在没有进行整个APP的情况下,里面的部分功能变了。即我部分的功能代码存在一个文件中,我在后台默默更换这些文件,下次你再打开APP,对应的功能或者样式就变了。

第4章节  __slots__的作用

  注意点:
  1、锁死你属性的使用范围,slots了那些属性,就只能使用哪些属性,不能再随意添加。
  2、对派生的类不起作用。

class cla():
    def __init__(self, name, age):
        self.name = name
        self.age = age

   #锁死范围
    __slots__ = ("name", "age")


c = cla("lalala", "12")
c.addr = "123"

你可能感兴趣的:(02Python学习笔记之二.五【作用域、动态添加属性方法、types.MethodType、slots】2019-08-18)