zoukankan      html  css  js  c++  java
  • 20170702-变量说明,静态方法,类方法区别,断点调试,fork,yield协程,进程,动态添加属性等。。

    概念:

      并行:同时运行

      并发:看似同时运行

     json后任然中文的问题

    import json
    
    d = {"名字":"初恋这件小事"}
    
    new_d1 = json.dumps(d)
    
    new_d = json.dumps(d, ensure_ascii=False)
    
    
    print(new_d1)
    print(new_d)

    变量说明

    xx: 公有变量
    _x:私有方法或属性,不可以通过 from somemodule import * 的方式导入,但是可以通过 import somemodule ,通过 somemodule._x的方式来调用
    __xx:无法在外部直接访问,类似于上面那个, 在类里面的时候,python偷偷的把这种方法变量改了名字 _函数名__变量名 可以通过 dir(对象) 来查看
    __xx__:如 __init__, 不要发明这样的名字
    xx_:用于避免与 Python 关键词冲突, 不推荐

    类相关

    静态方法:
      存在于类中的普通方法,对象调用的时候,不会自动往里面传递 self 的参数,,但是如果不主动往里面传递self(对象)的时候,那就不能调用 self.属性(方法)了
    只是名义上属于类
    类方法:
      这个方法里面只能访问类变量(引用的时候也是要写self.变量),不能访问实例变量。

     get/set方法的升级---版本一

     1 #! /usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 # __author__ = "Always"
     4 # Date: 2017/7/2
     5 
     6 # propetry的使用
     7 
     8 class Test(object):
     9     def __init__(self):
    10         self.__num = 100
    11 
    12 
    13     def getNum(self):
    14         print("++++++++++++getNum++++++++++++")
    15         return self.__num
    16 
    17     def setNum(self, newNum):
    18         print("++++++++++++setNum++++++++++++")
    19         self.__num = newNum
    20 
    21     num = property(getNum, setNum)     # 位置参数(self, fget=None, fset=None, fdel=None, doc=None),get 在前面, set在后面
    22 
    23 t = Test()
    24 
    25 print(t.getNum())
    26 
    27 t.setNum(200)                       # 正常情况下,都是这么调用
    28 print(t.getNum())
    29 
    30 
    31 t.num = 50             # 使用 property 后,将get、set设置成了属性,这样的话,调用起来就比较方便了。可以直接使用
    32 
    33 print(t.num)
    get/set升级版本一

    get/set方法的升级---版本二

     1 # Date: 2017/7/2
     2 
     3 # propetry的使用
     4 
     5 class Test(object):
     6     def __init__(self):
     7         self.__num = 100
     8 
     9 # get写前面,set写后面,两个函数名字一样,函数名为后面的取值依据,个体前面写 property,set写 函数名.setter
    10     @property
    11     def num(self):
    12         print("++++++++++++getNum++++++++++++")
    13         return self.__num
    14 
    15     @num.setter
    16     def num(self, newNum):
    17         print("++++++++++++setNum++++++++++++")
    18         self.__num = newNum
    19 
    20     @num.deleter
    21     def num(self):
    22         print("++++++++++++deNum++++++++++++")
    23         del self.__num
    24 
    25 # 话句话说, 前面加 property 的时候,就把这个函数变成了一个属性(变量) 这样的话,代表可以直接执行
    26 # 这种情况下如果遇到有参数的时候,传参数可以参考 setter 这个赋值的操作,也就是,写两个咯。。。多试大兄弟
    27 t = Test()
    28 
    29 t.num = 50
    30 print(t.num)
    31 
    32 del t.num   # 通过这个可以删除 __num  这个私有属性
    33 
    34 # 上面就是三个属性的装饰器
    35 # 通常可以只提供一个查询的结果的接口给别人(这个函数里面可可以添加好多的流程)
    get/set升级版本二

    python语言的动态性,即可以给类和对象动态的添加方法和属性

     1 #! /usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 # __author__ = "Always"
     4 # Date: 2017/7/2
     5 
     6 import types
     7 
     8 class Person(object):
     9     def __init__(self, newName, newAge):
    10         self.name = newName
    11         self.age  = newAge
    12 
    13 p1 = Person("p1", 18)
    14 
    15 p1.sex = "male"
    16 
    17 def run(self):
    18     print("%s can run..."%self.name)
    19 
    20 
    21 p1.run = types.MethodType(run, p1)      # 给对象添加方法
    22 # 后面那句话的主要意思是,将 p1 与 run 绑定到一起,下次执行 run 的时候,自动把 p1 传进去
    23 # 这句话的意思是,将后面得到的一个返回结果给前面的 p1 中的 run 这个变量,当然了,前面p1.run
    24 # 也可以换成任意的变量名,下次可以通过这个变量名来调用这个函数,但是没什么意义
    25 
    26 print(p1.sex)
    27 p1.run()
    28 
    29 @staticmethod
    30 def hehe():
    31     print("给类添加静态方法")
    32 
    33 Person.hehe = hehe          # 给类添加静态方法
    34 
    35 Person.hehe()
    36 p1.hehe()
    37 
    38 
    39 @classmethod
    40 def fire(fir):
    41     print("给类添加类方法")
    42 
    43 Person.fire = fire
    44 
    45 Person.fire()
    46 
    47 p1.fire()
    类和方法动态添加属性和方法

    禁止添加动态方法

     1 #! /usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 # __author__ = "Always"
     4 # Date: 2017/7/2
     5 
     6 class Person(object):
     7     __slots__ = ("name", "age", "sex")
     8 
     9 
    10 p1 = Person()
    11 
    12 p1.name = 'zhang'
    13 p1.age = 18
    14 p1.sex = 'male'
    15 
    16 print(p1.name, p1.age, p1.sex)
    17 
    18 
    19 class Person(object):
    20     __slots__ = ("name", "age", "sex")
    21 
    22     def __init__(self, name, age, sex):
    23         self.name = name
    24         self.age = age
    25         self.sex = sex
    26 
    27 p1 = Person('zhang', 18, 'male')
    28 
    29 
    30 print(p1.name, p1.age, p1.sex)
    31 
    32 
    33 # 试过了,__slote__ 不可以放在 __init__ 里面
    禁止添加动态方法

    类做装饰器,其实原理和 函数 做装饰器原理差不多

     1 #! /usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 # __author__ = "Always"
     4 # Date: 2017/7/2
     5 
     6 
     7 class Outer(object):
     8     def __init__(self, func):
     9         print("---类做装饰器,初始化---")
    10         print("func name is %s"%func.__name__)
    11         self.__func = func
    12 
    13     def __call__(self, *args, **kwargs):
    14         print("---装饰器里面的功能---")
    15         self.__func()
    16 
    17 @Outer
    18 def foo():
    19     print("---foo---")
    20 
    21 
    22 foo()
    实例一
     1 # __call__ 这个函数,可以通过 实例的对象的本来来调用这个函数,所以说,这个就可以把类来用作装饰器了
     2 # of couse,这个函数是可以有返回值的
     3 class Person(object):
     4     def __init__(self, name):
     5         self.name = name
     6 
     7     def __call__(self, *args, **kwargs):
     8         print(self.name)
     9         return '1231231'
    10 
    11 
    12 p1 = Person('zhang')
    13 
    14 print(p1())
    可以有返回值

    断点调试

    这个是写完了的情况下
    python -m pdb test1.py
    
    l---->list 显示当前的代码
    n---->next 向下执行一行代码
    c---->continue 继续执行代码
    
    在这个模式中,使用 b 可以添加端点
    >>b 7   意思是在第七行添加端点
    >>b     可以看到所有断点及序号
    >>clear 断点序号        删除
    
    b---->break 添加端点
    
    clear--> 删除断点
    
    在call(函数)的时候,敲 s 回车,然后再 l,进入 call 里面执行
    
    p a--->step 查看 a 变量的值
    
    a--->args 查看所有形参的数据
    
    q---->quit 退出调试
    
    r---->return  快速执行道函数的最后一行
     1 #! /usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 # __author__ = "Always"
     4 # Date: 2017/7/2
     5 
     6 import pdb
     7 
     8 def add(a,b):
     9     c = a + b
    10     return c
    11 
    12 
    13 pdb.run("add(3,4)")   # 注意书写方式,括号里面是 引号,意思是让 pdb.run 来调用它,执行后 先输入 s 进入这个函数里面
    14 
    15 
    16 
    17 #==============另一种方法,文件里面下断点-程序里埋点,遇到就开始调试---------------
    18 
    19 def sub(a,b):
    20     c = a - b
    21     return c
    22 
    23 
    24 pdb.set_trace()
    25 ret = sub(3, 2)             # 直行道这里开始调试模式
    26 print(ret)
    其它两种断点使用方法

     多任务

     yield实现协程

     1 #! /usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 # __author__ = "Always"
     4 # Date: 2017/7/2
     5 
     6 def fun1():
     7     while True:
     8         print("--1--")
     9         yield None    # 可以没有返回值
    10 
    11 def fun2():
    12     while True:
    13         print("--2--")
    14         yield None
    15 
    16 f1 = fun1()
    17 f2 = fun2()
    18 
    19 
    20 while True:
    21     next(f1)
    22     next(f2)

    实现多进程

    import os

    res = os.fork()--->主进程得到的值大于0, 子进程得到的值为0
    print('heheh')

     1 #coding:utf-8
     2  
     3 import os
     4 
     5 res = os.fork()
     6 
     7 if res:
     8     while True:
     9         print("Are you OK?")
    10 else:
    11     while True:
    12         print("I am OK")

    # 上面的 os.fork 会创建一个新的进程,执行下面的代码。
    # 也就是说,print 会被执行两次
    # os.fork() 会返回两次,一次是 0, 和其它,因为新的进程也要从这里往下走
    # 这样的话就相当于执行了两次下面的流程。你可以判断返回值,让它执行两个内容
    # 这个方法只可以在非 Windows 上面执行,如:linux, windows不支持这个
    # 主进程结束后,子进程不会被杀死
    # 缺点,占得资源比较大

    os.getpid() ---> 进程 id
    os.getppid() ---> 父进程 id

     1 #coding:utf-8
     2 
     3 import os
     4 import time
     5 
     6 a = 100
     7 
     8 res = os.fork()
     9 
    10 if res:
    11     for i in range(100):
    12         print(a)
    13         a -= 1
    14         time.sleep(0.01)
    15 else:
    16     for i in range(100):
    17         print(a)
    18         a += 1
    19         time.sleep(0.01)
    20 print("The last value:",a)

    # 前面的结果我忽略了,直接看最后的结果吧
    >>> The last value: 0
    >>> The last value: 200

    # 这说明了,多进程之间的全局变量是不共享的,其实很容理解,这两个已经相当于独立了。。。。

    # 后期学习进程间的通信

    # 进程后面再接 fork 的话,那么就相当于再执行 两次(主进程一次,子进程一次)

    例:
      os.fork()
      os.fork()
      os.fork()
      print("----1----")
    会被打印8次

    ======解决windows不能用的问题======
    可以用于 windows 以及 linux,由模块的接口来调用,更具不同的电脑

    from multiprocessing import Process
    用这个方法,主进程会等待所有子进程结束

    windows 比较奇怪,windows在起线程的时候需要把 start 放在 __name__ 里面,这是由于操作系统机制不同导致的,windows在起这个进程的时候,会导入这个文件,读取这个文件,如果不放在 __name__ 里面的话,就会进入无线起新进程的状态,所以会报错。

     1 # ! /usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 # __author__ = "Always"
     4 # Date: 2017/7/2
     5 
     6 from multiprocessing import Process, freeze_support
     7 import time
     8 
     9 def foo():
    10     for i in range(5):
    11         print("---foo---")
    12         time.sleep(1)
    13 
    14 
    15 def main():
    16     for i in range(5):   # 主程序继续执行
    17         print("---main---")
    18         time.sleep(1)
    19 
    20 if __name__ == "__main__":
    21     freeze_support()    # 那啥,我也不知道为什么加这个,不加反正也没事,等到讲到的时候重新做笔记吧
    22     p = Process(target=foo)  # 创建一个对象,让后,将函数赋值给 target
    23     p.start()  # 调用对象的方法,开始执行 foo 函数里面的代码
    24 
    25     p.join()   # 阻塞,等到子进程结束后,主程序才会继续往下走
    26                # 里面可以写个时间,如果到达这个秒数还没结束,那么主程序往后走
    27 
    28     p.terminate() # 不管子程序有没有结束,都kill掉它
    29 
    30     main()
  • 相关阅读:
    《别让不会记笔记害了你》豆瓣:3.9
    《费曼学习法用输出倒逼输入》 豆瓣:6.6
    《面人麻生》豆瓣:8.8 &《哈瓦那》豆瓣:7.8
    C# 获取汉语拼音全码及简码
    SQL Server 获取汉语拼音简码
    ASP.NET 3.5中的ListView控件和DataPager控件
    Appliction_BeginRequest
    身份证验证
    取得数据库表信息的Sql语句
    Spark shuffle失败的可能原因 及解决办法
  • 原文地址:https://www.cnblogs.com/alwaysInMe/p/7108035.html
Copyright © 2011-2022 走看看