Python一切皆对象 
在python中,函数也是一个变量,可以指向不同的函数对象
此处将函数抽象为变量
def  f (x ):    return  x * x r = map (f, [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]) print (list (r))[1 , 4 , 9 , 16 , 25 , 36 , 49 , 64 , 81 ] 
from  functools import  reducedef  fn (x, y ):    return  x * 10  * y def  char2num (s ):    digits = {'0' : 0 , '1' : 1 , '2' : 2 , '3' : 3 , '4' : 4 , '5' : 5 , '6' : 6 , '7' : 7 , '8' : 8 , '9' : 9 }     return  digits[s] print (reduce(fn, map (char2num, '13579' )))
利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart']:
 from  functools import  reducedef  normalize (name ):    return  name.capitalize() L1 = ['adam' , 'LISA' , 'barT' ] L2 = list (map (normalize,L1)) print (L2)
 
Python提供的sum()函数可以接受一个list并求和,请编写一个prod()函数,可以接受一个list并利用reduce()求积:
 from  functools import  reducedef  prod (L ):    def  f (x, y ):         return  x * y     return  reduce(f, L) print ('3 * 5 * 7 * 9 =' , prod([3 , 5 , 7 , 9 ]))
 
利用map和reduce编写一个str2float函数,把字符串'123.456'转换成浮点数123.456:
 from  functools import  reducedef  str2float (s ):    def  fn (x, y ):         return  x * 10  + y     def  char2num (s ):         digits = {'0' : 0 , '1' : 1 , '2' : 2 , '3' : 3 , '4' : 4 , '5' : 5 , '6' : 6 , '7' : 7 , '8' : 8 , '9' : 9 }         return  digits[s]     n = s.index('.' );     s1 = list (map (char2num, s[:n]));     s2 = list (map (char2num, s[n + 1 :]));     return  reduce(fn, s1) + reduce(fn, s2) * 0.1  ** len (s2); print ('str2float(\'123.456\') =' , str2float('123.456' ));if  abs (str2float('123.456' ) - 123.456 ) < 0.00001 :    print ('测试成功!' ); else :    print ('测试失败!' ); 
 
 
根据返回值是true或false来丢弃值
def  is_odd (n ):    return  n % 2  == 1  list (filter (is_odd, [1 , 2 , 4 , 5 , 6 , 9 , 10 , 15 ]))
sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序,
sorted ([36 , 5 , -12 , 9 , -21 ], key=abs )
函数作为方法返回,但是每次返回的函数不是同一个函数
def  lazy_sum (*args ):    def  sum ():         ax = 0          for  n in  args:             ax = ax + n         return  ax     return  sum  f = lazy_sum(1 ,3 ,5 ,7 ,9 ) print (f, f())
返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
def  count ():    fs = []     for  i in  range (1 , 4 ):         def  f ():              return  i*i         fs.append(f)     return  fs f1, f2, f3 = count() print (f1(), f2(), f3())
修改为,用函数的参数绑定循环变量当前的值
def  count ():    def  f (j ):         def  g ():             return  j*j         return  g     fs = []     for  i in  range (1 , 4 ):         fs.append(f(i))      return  fs f1, f2, f3 = count() print (f1(), f2(), f3())
使用外层函数变量时,如果局部函数对外层变量赋值,编译器就会认为变量是局部变量,需要使用nonlocal 进行声明
def  inc ():    x = 0      def  fn ():                  x = x + 1          return  x     return  fn f = inc() print (f()) print (f()) 
利用闭包返回一个计数器函数,每次调用它返回递增整数:
def  createCounter ():    x = 0      def  counter ():         nonlocal  x         x = x + 1          return  x     return  counter f = createCounter() print (f(), f(), f(), f(), f())  d = createCounter() if  [d(), d(), d(), d()] == [1 , 2 , 3 , 4 ]:    print ('测试通过!' ) else :    print ('测试失败!' ) 
lambda x: x * x 这个表达式就是匿名函数,冒号前面的x表示函数参数。
def  f (x ):    return  x * x g = lambda  x: x * x if  f(2 ) == g(2 ):    print ("相等" ) 
由于log()是一个decorator,返回一个函数,所以,原来的now()函数仍然存在,只是现在同名的now变量指向了新的函数,于是调用now()将执行新函数,即在log()函数中返回的wrapper()函数。
def  log (func ):    def  wrapper (*args, **kw ):         print ('call %s():'  % func.__name__)         return  func(*args, **kw)     return  wrapper @log   def  now ():    print ('2015-3-25' ) now() 
在面向对象(OOP)的设计模式中,decorator被称为装饰模式。OOP的装饰模式需要通过继承和组合来实现,而Python除了能支持OOP的decorator外,直接从语法层次支持decorator。Python的decorator可以用函数实现,也可以用类实现。
decorator也可义传入参数,要编写一个返回decorator的高阶函数,写出来会更复杂。
def  log (text ):    def  decorator (func ):         def  wrapper (*args, **kw ):             print ('%s %s():'  % (text, func.__name__))             return  func(*args, **kw)         return  wrapper     return  decorator @log('execute'  def  now ():    print ('2015-3-25' )     return  0  now() 
但是以上的写法都是不完整的,输出函数的__name__就知道都被改变了
def  log (text ):    def  decorator (func ):         def  wrapper (*args, **kw ):             print ('%s %s():'  % (text, func.__name__))             return  func(*args, **kw)         return  wrapper     return  decorator @log('execute'  def  now ():    print ('2015-3-25' )     return  0  print (now.__name__)
需要使用functools模块中的wraps(func)来解决,如下:
import  functoolsdef  log (func ):    @functools.wraps(func )     def  wrapper (*args, **kw ):         print ('call %s():'  % func.__name__)         return  func(*args, **kw)     return  wrapper import  functoolsdef  log (text ):    def  decorator (func ):         @functools.wraps(func )         def  wrapper (*args, **kw ):             print ('%s %s():'  % (text, func.__name__))             return  func(*args, **kw)         return  wrapper     return  decorator 
请设计一个decorator,它可作用于任何函数上,并打印该函数的执行时间:
import  functoolsimport  timedef  metric (fn ):    @functools.wraps(fn )     def  wrapper (*args, **kw ):         begin = time.time()         x = fn(*args, **kw)         end = time.time()         t = end - begin         print ('%s executed in %s ms'  % (fn.__name__, t))         return  x     return  wrapper @metric def  fast (x, y ):    time.sleep(0.0012 )     return  x + y @metric def  slow (x, y, z ):    time.sleep(0.1234 )     return  x * y * z f = fast(11 , 22 ) s = slow(11 , 22 , 33 ) if  f != 33 :    print ('测试失败!' ) elif  s != 7986 :    print ('测试失败!' ) 
import  functoolsint2 = functools.partial(int , base=2 ) print (int2('1000000' ))max2 = functools.partial(max , 10 ) print (max2(5 , 6 , 7 ))
' a test module ' __author__ = 'Qi Xiang Dong'  import  sysdef  test ():         args = sys.argv      if  len (args)==1 :         print ('Hello, world!' )     elif  len (args)==2 :         print ('Hello, %s!'  % args[1 ])     else :         print ('Too many arguments!' ) if  __name__=='__main__' :    test() 
https://pypi.org/ 
class  People (object     def  eat (self ):         pass           def  learn (self ):         pass      def  sleep (self ):         pass  class  Student (People ):         def  __init__ (self, name, score ):                  self.__name = name         self.__score = score     def  print_score (self ):         print ('%s: %s'  % (self.__name, self.__score))     def  set_name (self, name ):         self.__name = name     def  set_score (self, score ):         self.__score = score     def  get_name (self ):         return  self.__name     def  get_score (self ):         return  self.__score          def  eat (self ):         print ("喜欢吃有营养的" ) bart = Student('Bart Simpson' , 59 ) lisa = Student('Lisa Simpson' , 87 ) bart.print_score() lisa.print_score() 
当我们定义一个class的时候,我们实际上就定义了一种数据类型,我们定义的数据类型和Python自带的数据类型。判断一个变量是否是某个类型可以用isinstance()判断
b = Animal()  c = Dog()  >>>  isinstance (c, Dog)True >>>  isinstance (c, Animal)True 
对扩展开放:允许新增Animal子类;
对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。
class  Animal (object     def  run (self ):         print ("Animal is running..." ) class  Dog (Animal ):    pass  class  Cat (Animal ):    def  run (self ):         print ('Cat is running...' ) class  Car (object     def  run (self ):         print ('Car is running...' ) class  Stone (object     pass  def  run_twice (animal ):    animal.run()     animal.run() run_twice(Animal()) run_twice(Dog()) run_twice(Cat()) run_twice(Car()) run_twice(Stone()) 
>>>  type (123 )<class  'int '> #比较是否是函数、表达式等 >>> type (fn )==types .FunctionType  True >>> type (abs types .BuiltinFunctionType  True >>> type (lambda  x: xtypes .LambdaType  True >>> type ((x for  x in  range (10  ) )==types .GeneratorType  True #isinstance ()函数,判断是否是对应类以及其父类 >>> isinstance (d, Dog ) and  isinstance (d, Animal ) True #isinstance ()函数,判断是否是多个类型中的一种 >>> isinstance ([1 , 2 , 3 ], (list , tuple  ) True #dir ()获得对象的所有属性和方法,返回一个lsit  >>> dir ('ABC'  ['__add__ ', '__class__ ',..., '__subclasshook__ ', 'capitalize ', 'casefold ',..., 'zfill '] #__len__ () 和 len ()等价 >>> len ('ABC'  3 >>> 'ABC '.__len__ () 3 #自己写len ()函数 class  MyDog (object     def  __len__ (self ):         return  100       dog = MyDog() print (len (dog))>>>  hasattr (obj, 'x' ) True >>>  obj.x9 >>>  hasattr (obj, 'y' ) False >>>  setattr (obj, 'y' , 19 ) >>>  hasattr (obj, 'y' ) True >>>  getattr (obj, 'y' ) 19 >>>  obj.y 19 def  readImage (fp ):    if  hasattr (fp, 'read' ):         return  readData(fp)     return  Non 
实例属性即动态创建的类属性 
类属性,类定义中有的属性 
**优先级:**实例属性 > 类属性 
 
>>>  class  Student (object ...      name = 'Student' ... >>>  s = Student() >>>  print (s.name) Student >>>  print (Student.name) Student >>>  s.name = 'Michael'  >>>  print (s.name) Michael >>>  print (Student.name) Student >>>  del  s.name >>>  print (s.name) Student 
同一类的实例对象可以动态绑定方法,但是其他对象则不能使用,只有给类绑定方法,所有的实例对象才能使用。
class  Student (object     pass  def  set_score (self, score ):    self.score = score Student.set_score = set_score  s = Student() s.set_score(17 ) print (s.score)
但同时,也希望能够限制不必的动态绑定
通过使用_slots _
class  Student (object     __slots__ = ('name' , 'age' )  
使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的:
class  Screen (object          @property     def  width (self ):         return  self._width      @width.setter     def  width (self, w ):         self._width = w     @property     def  height (self ):         return  self._height     @height.setter     def  height (self, h ):         self._height = h     @property     def  resolution (self ):         return  self.width * self.height s = Screen() s.width = 1024  s.height = 768  print ('resolution =' , s.resolution)if  s.resolution == 786432 :    print ('测试通过!' ) else :    print ('测试失败!' ) 
属性的方法名不要和实例变量重名是因为调用s.width时,首先转换为方法调用,在执行return self.width时,又视为访问self的属性,于是又转换为方法调用,造成无限递归,最终导致栈溢出报错RecursionError。
python 与c++相同都支持多继承,来满足多个类复杂关系的声明,同时有MixIn这种我
class  Mammal (object     pass  class  RunnableMixIn :    pass  class  CarnivorousMixIn :    pass  class  Dog (Mammal, RunnableMixIn, CarnivorousMixIn ):    pass  
new __new _  是一种负责创建类实例的静态方法,它无需使用 staticmethod 装饰器修饰,且该方法会优先 init () 初始化方法被调用。
class  DemoClass :    instances_created = 0      def  __new__ (cls, *args, **kwargs ):         print ("__new__():" , cls, args, kwargs)         instance = super ().__new__(cls)          instance.number = cls.instances_created           cls.instances_created += 1          return  instance     def  __init__ (self, attribute ):         print ("__init__():" , self, attribute)           self.attribute = attribute test1 = DemoClass("abc" ) test2 = DemoClass("xyz" ) print (test1.number, test1.instances_created)print (test2.number, test2.instances_created)__new__(): <class  '__main__ .demoClass '> ('abc' , __init__ ():object  at 0x0000023681717B50 > abc__new__(): <class  '__main__ .demoClass '> ('xyz' , __init__ ():object  at 0x0000023681717A60 > xyz0  2 1  2 
str _class  Student (object     def  __init__ (self, name ):         self.name = name     def  __str__ (self ):         return  'Student object (name: %s)'  % self.name print (Student('Michael' ))s = Student('Michael' ) print (s)Student object  (name: Michael) <__main__.Student object  at 0x109afb310 > 
直接显示变量调用的不是__str__(),而是__repr__(),两者的区别是__str__()返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串,也就是说,__repr__()是为调试服务的。
iter _如果想使你的类支持像list或可以用for … in 循环的类,则需要_iter _,以斐波那契数列为例,写一个Fib类,可以作用于for循环:
class  Fib (object     def  __init__ (self ):         self.a, self.b = 0 , 1       def  __iter__ (self ):         return  self      def  __next__ (self ):         self.a, self.b = self.b, self.a + self.b          if  self.a > 100000 :              raise  StopIteration()         return  self.a  
getitem _支持for循环,就想支持像list一样的取其中的元素
class  Fib (object     def  __getitem__ (self, n ):         a, b = 1 , 1          for  x in  range (n):             a, b = b, a + b         return  a 
这部分还可以支持切片等的高级功能,但是需要自己写更多的代码,具体参考https://www.liaoxuefeng.com/wiki/1016959663602400/1017590712115904
from  enum import  Enum, uniqueMonth = Enum('Month' , ('Jan' , 'Feb' , 'Mar' , 'Apr' , 'May' , 'Jun' , 'Jul' , 'Aug' , 'Sep' , 'Oct' , 'Nov' , 'Dec' )) @unique class  Weekday (Enum ):    Sun = 0        Mon = 1      Tue = 2      Wed = 3      Thu = 4      Fri = 5      Sat = 6  for  name, member in  Month.__members__.items():    print (name, '=>' , member, ',' , member.value) print (Weekday.Sun)print (Weekday.Sun.value)Jan => Month.Jan , 1  Feb => Month.Feb , 2  Mar => Month.Mar , 3  Apr => Month.Apr , 4  May => Month.May , 5  Jun => Month.Jun , 6  Jul => Month.Jul , 7  Aug => Month.Aug , 8  Sep => Month.Sep , 9  Oct => Month.Oct , 10  Nov => Month.Nov , 11  Dec => Month.Dec , 12  Weekday.Sun 0 
在python中class的定义是运行时动态创建的,而创建class的方法就是使用type()函数。因此type函数可以创建类,无需用class定义
def  fn (self, name='world'  ):    print ('Hello, %s.'  % name) Hello = type ('Hello' , (object ,), dict (hello=fn))   h = Hello() h.hello() 
要创建一个class对象,type()函数依次传入3个参数:
class的名称; 
继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法; 
class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。 
 
这种方法和使用class来创建是完全相同的
metaclass 
可以把类看成是metaclass创建出来的“实例”。
连接起来就是:先定义metaclass,就可以创建类,最后创建实例。
我参考了这个文章,类与元类(metaclass)的理解  。讲的比较透彻有补充再来添加。
和大多数高级语言相同,python也有自己的错误处理函数
try :    print ('try...' )     r = 10  / int ('2' )     print ('result:' , r) except  ValueError as  e:    print ('ValueError:' , e) except  ZeroDivisionError as  e:    print ('ZeroDivisionError:' , e) else :    print ('no error!' ) finally :    print ('finally...' ) print ('END' )
python的错误类型也都是class,存在继承关系,高的类型会把低的类型覆盖。
常见的错误类型和继承关系看这里:
https://docs.python.org/3/library/exceptions.html#exception-hierarchy 
通过函数调用栈,来看报错信息,从而找到错误的位置
def  foo (s ):    return  10  / int (s) def  bar (s ):    return  foo(s) * 2  def  main ():    bar('0' ) main() Traceback (most recent call last):   File "E:\Python_item\Item1\test.py" , line 11 , in  <module>     main()   File "E:\Python_item\Item1\test.py" , line 9 , in  main     bar('0' )   File "E:\Python_item\Item1\test.py" , line 6 , in  bar     return  foo(s) * 2    File "E:\Python_item\Item1\test.py" , line 3 , in  foo     return  10  / int (s) ZeroDivisionError: division by zero 
使用logging()函数可以记录错误
参考https://www.liaoxuefeng.com/wiki/1016959663602400/1017607179232640
https://docs.python.org/zh-cn/3/tutorial/datastructures.html#using-lists-as-stacks 
python的数据结构都用类来封装
class  Stack :    def  __init__ (self ):         self.stack = [] 	     def  push (self, value ):         self.stack.append(value) 	     def  pop (self ):         return  self.stack.pop() 	     def  get_top (self ):         if  len (self.stack) > 0 :             return  self.stack[-1 ]         else :             return  None  x = Stack() 
但其实这样做完就发现完全不需要用class来建立堆栈,只需要用list足够了,类似队列的操作也可以用类来封装