Python类及多线程

模块  import 

导入模块是python最常用的一种便捷用法,python有各式各样的开源模块供使用,也可以自定义一个模块使用

import  XXXXXXXXXX   as  x 

from  XXXXXXXXXX  import  X

 

面向对象  把数据和对数据操作用一种叫做对象的东西包裹起来,类:吧共同属性抽象出来,对象:实例化中设置各自属性;

class  Pople():   定义一个类 首字母大写 然后写这个类的构造函数

  def __init__(self,name,sex):

    self.__name = name   将name定义为一个不可改变的变量  不能通过外部调用函数变量改变其值,需要类里内部函数做变更

    self.sex = sex

  def eat():

    pass

class Zhangsan(Pople):

  def __init__(self,name,sex,age,new)      或者使用super来初始化 

    self.name = name   super().__init__(name)  将子类中的值放到父类中去初始化,

    self.age = age

 

也可以不写类的构造函数,使用set 和get方法   类在初始化的时候  还不确定参数的情况下可以使用set get
class Persion:

def set_name(self,name):
self.name = name

def get_name(self):
return self.name

if __name__=='__main__':
zhangsan=Persion()
zhangsan.set_name('lalalla')
print(zhangsan.get_name())

类的继承

继承父类时,可以不写init方法(默认会使用父类的init);

重写init会使用实例自身写的init

重写init时想要在父类的基础上重写的话可以使用  super(defName,self).__init__( )

class Father(object):
def __init__(self, name):
self.name = name
print("name: %s" % (self.name))

def getName(self):
return 'Father ' + self.name

class Son(Father):
def __init__(self, name):
super(Son, self).__init__(name) #super在使用的是 注意父类要继承Object python3中是没有这个问题的
     #Father.__init__(sele,name) #也可以这么用
print("hi")
self.name = name

def getName(self):
return 'Son ' + self.name

name: runoob #先调用父类的init
hi 
Son runoob

 

多态:重写父类的方法

类具有继承关系,并且子类类型可以向上转型看做父类类型,如果我们从 Person 派生出 Student和Teacher ,并都写了一个 whoAmI() 方法:
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def whoAmI(self):
return 'I am a Person, my name is %s' % self.name

class Student(Person):
def __init__(self, name, gender, score):
super(Student, self).__init__(name, gender)
self.score = score
def whoAmI(self):
return 'I am a Student, my name is %s' % self.name

class Teacher(Person):
def __init__(self, name, gender, course):
super(Teacher, self).__init__(name, gender)
self.course = course
def whoAmI(self):
return 'I am a Teacher, my name is %s' % self.name
在一个函数中,如果我们接收一个变量 x,则无论该 x 是 Person、Student还是 Teacher,都可以正确打印出结果:

def who_am_i(x):
print x.whoAmI()

p = Person('Tim', 'Male')
s = Student('Bob', 'Male', 88)
t = Teacher('Alice', 'Female', 'English')

who_am_i(p)
who_am_i(s)
who_am_i(t)
运行结果:

I am a Person, my name is Tim
I am a Student, my name is Bob
I am a Teacher, my name is Alice
这种行为称为多态。也就是说,方法调用将作用在 x 的实际类型上。s 是Student类型,它实际上拥有自己的 whoAmI()方法以及从 Person继承的 whoAmI方法,
但调用 s.whoAmI()总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。
由于Python是动态语言,所以,传递给函数 who_am_i(x)的参数 x 不一定是 Person 或 Person 的子类型。任何数据类型的实例都可以,只要它有一个whoAmI()的方法即可

静态方法:

使用装饰器@staticmethod。

静态方法是类中的函数,不需要实例。静态方法主要是用来存放逻辑性的代码,逻辑上属于类,但是和类本身没有关系,也就是说在静态方法中,不会涉及到类中的属性和方法的操作。可以理解为,静态方法是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护。

 import time

class TimeTest(object):
def __init__(self, hour, minute, second):
self.hour = hour
self.minute = minute
self.second = second

@staticmethod
def showTime():
return time.strftime("%H:%M:%S", time.localtime())


print(TimeTest.showTime())
t = TimeTest(2, 10, 10)
nowTime = t.showTime()
print(nowTime)

使用了静态方法(函数),然而方法体中并没使用(也不能使用)类或实例的属性(或方法)。若要获得当前时间的字符串时,并不一定需要实例化对象,此时对于静态方法而言,所在类更像是一种名称空间。

其实,我们也可以在类外面写一个同样的函数来做这些事,但是这样做就打乱了逻辑关系,也会导致以后代码维护困难。


类方法

使用装饰器@classmethod。

原则上,类方法是将类本身作为对象进行操作的方法。假设有个方法,且这个方法在逻辑上采用类本身作为对象来调用更合理,那么这个方法就可以定义为类方法。

另外,如果需要继承,也可以定义为类方法。


class ClassTest(object):
__num = 0

@classmethod
def addNum(cls):
cls.__num += 1

@classmethod
def getNum(cls):
return cls.__num

# 这里我用到魔术方法__new__,主要是为了在创建实例的时候调用累加方法。
def __new__(self):
ClassTest.addNum()
return super(ClassTest, self).__new__(self)


class Student(ClassTest):
def __init__(self):
self.name = ''

a = Student()
b = Student()
print(ClassTest.getNum())
 

Property 方法   一个方法被定义为property的时候,调用方法会和实例方法不一样,可以把一个类中的方法当成属性调用.

 

下划线和双下划线的作用:

变量名如果是以__双下划线开头的就变成了一个私有变量

变量名以_开头的,这样的变量可以被外部访问,但是按照预定俗称的规定,一般不要随意改动

变量名以__xxx__开头的,一般是系统自定义的变量,不建议占用.

 

装饰器:@ 装饰器本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景,装饰器是解决这类问题的绝佳设计。有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码到装饰器中并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

  https://www.runoob.com/w3cnote/python-func-decorators.html

 

import logging
def use_logging(func):

def wrapper():
logging.warn("%s is running" %func.__name__)
return func()
return wrapper

@use_logging
def foo():
print("i am foo")

foo()

输出:
i am foo
WARNING:root:foo is running

 

 

自定义包:目录下有 init 才能被外部引用

 

with的自定义

with中包含了 __enter__ 和  __exit__  方法

class  Testwith():

  def __enter__(self):

    print('enter')

  def__exit__(self,exc_type,exc_val,exc_tb):

    if exc_tb is None:

      print(‘exit normal’)

    else:

      print(‘exit with  exception’)

with  Testwith():   执行之前会先执行enter里面的逻辑  执行完之后会去执行exit的逻辑   如果有异常  可以通过exc捕获

  print(‘test’)

  raise NameError(‘Exception’)

多线程编程 

最多线程是有两个原因决定的,内存容量和软件限制,虽然线程是轻量级进程,但是创建线程也是要消耗内存的,初始状态下消耗大小就是内存栈了,每创建一个线程为其分配一个线程栈,还有一种限制是系统的配置参数限制,比如在linux上每进程创建线程是1024个,在local_lim.h中定义,可以使用ulimt -a查看线程栈大小

不使用多线程的情况

def  myThread (arg1,arg2):

  print(‘%s %s’ %(arg1,arg2))

for  i  in  range(1,6,1):

  t1 = myThread(i , i+1)

使用多线程的情况:

import  threading

from threading import  current_thread

def  myThread(arg1,arg2):

  print(current_thread().getName(),'start') #显示当前线程的状态

  print('%s,%s' %(arg1,arg2))

  time.sleep(1)

  print(current_thread().getName(),'stop')

for  i   in  range(1,6,1):

  t1 = threading.Thread(target=myThread,args=(i, i+1))

  t1.start()

t1.join()    不调用jion方法,执行完子线程之前就会先把主线程执行完毕,

print(current_thread().getName(),'end')

 

多线程经典案例:生产者和消费者  创建一个队列。,使用线程进行生产数据到队列和消费队列中的数据

from threading import current_thread,Thread

import time

import random

from queue import Queue

queue = Queue(5)  创建一个长度为5的队列

class  ProducerThread(Thread):

  def  run(self):

    name = current_thread().getName()  获取线程名称

    nums = range(100)

    global queue

    while Ture:

      num = random.chose(nums)

      queue.put(num)   往队列里写入数据

      t = random.randint(1,3)

      time.sleep(t)

class  ConsumerThread(Thread):

   def run (self):

    name = current_thread().getName()

    globle queue

    while True:

      num = queue.get()

      queue.task_done()

      t = random.andomint(1,5)

      time.sleep(t)

p1 = ProducerThread(name = 'p1')

p1.run()    单独运行run方法,会把主进程当成一个线程来看,执行的代码空间在MainThread主线程中,

p1.start()   执行start方法,python会创建一个新线程,叫 Thread-1 然后再去调用run()来运行

c1 = ConsumerThread(nem = 'c1')

c1.start()

 

posted @ 2019-06-20 15:51  头大点怎么了  阅读(4970)  评论(0编辑  收藏  举报