Python学习笔记(一)
编码
Python2默认编码为ASCII
Python3默认编码为UTF8
在文件开头使用下面语句修改编码为UTF8
# coding=utf-8
字符串
Python不支持单个字符,即使单个字符也是一个字符串
字符串通过单引号或者双引号包围,三个单引号可以包围多行字符串
字符串对象结合下标运算可以获取对应位置字符(字符串)
通过[:]运算可以获取对应下标区间截取的子串
#!/usr/bin/python
var1 = 'Hello World!'
var2 = "Python Runoob"
print "var1[0]: ", var1[0]
print "var2[1:5]: ", var2[1:5]
智能补齐
Python中不需要主动在行末添加分号,会智能补齐
注释与字符串
单行注释,通过在行的头部加上#,如
#这是注释
多行注释使用三个单引号或者三个双引号作为起止符,如
'''
这是注释
'''
"""
这是注释
"""
同时,三个单引号也可以作为多行字符串的输入,比如
words = ''' I am
eetal '''
变量定义
Python中的变量不需要进行声明即可直接初始化
只有初始化以后的变量才会被创建,比如
#!/usr/bin/python
# coding=utf-8
counter = 100 # 赋值变量
print counter
布尔值
Python中,非0和非空(null)值为true,False,0,’’,[],{},(),null为false
特殊运算符
- **
幂运算, x ** y 代表 x的y次方 - **=
幂运算后赋值 - //
除商向下取整 ,x // y 代表 x除以y的结果向下取整 - //=
除商向下取整后赋值 - and
and逻辑(二元运算),如果左值为False返回False,否则返回右值 - or
or逻辑(二元运算),如果左值不是0,返回左值,否则返回右值 - not
not逻辑(一元运算),如果运算值为True返回False,运算值为False返回True - in
返回在右值(集合)中,是否存在元素等于左值。独特的,in关键字与for循环搭配有其他含义。 - not in
返回在右值(集合)中,是否没有元素等于左值 - is
返回左值和右值是否是同一个对象(内存地址一致,通过id函数可以获取对象内存地址) - is not
返回左值和右值是否不是同一个对象(内存地址不一致)
条件语句
Python中,elif代表其他语言的else if。
Python的条件表达式不需要小括号包裹,在条件结尾加上冒号。
Python中,不使用花括号包括语句。
规定,相同缩进量的语句,默认被包裹为一个复合语句(一个缩进量为4个空格)。
if 判断条件1:
执行语句1……
elif 判断条件2:
执行语句2……
else:
执行语句4……
循环语句
Python中的循环语句可以添加一个else子句,将会在循环正常执行结束后执行(非break)
- for循环
Python中,在for循环中使用in关键字,可以迭代一个集合,将元素赋值到临时变量,如for temp in sequence: print(temp) else: print('end')
- while循环
while 判断条件: 执行语句 else: print('end')
函数定义
Python的函数不需要指定返回值类型,通过def关键字定义函数
函数第一行缩进可以填写一串字符串常量,代表函数说明,不会作为代码编译
同样的,函数体不需要使用花括号,而是一个复合语句(满足一个以上单位的相对缩进的的语句为函数内部语句)
def name( parameters ):
"函数_文档字符串"
code
return [expression]
Python3新增参数和返回值注释,参数注释通过添加:在右侧编写,返回值注释通过在形参括号后,结束冒号前添加->,如何在->右侧编写注释。需要注意的是,如果形参有默认值,赋值语句应该放在注释之后
def f(age : '年龄默认22' = 22)->'返回值注释':
return age
可变参数
- *args: 一个*修饰的形参代表,接收多个非键值对输入(元组)
- **kwargs: 两个*修饰的形参代表,接收多个键值对输入(字典)
上述的args和kwargs只是一个形参名,无特殊意义,也可以是其他名称
def f(*args,**kwargs):
print(args)
print(kwargs)
f(1,2,3,name='yyt',age=22)
pass语句
pass关键字代表一个空语句,主要为了占位置,满足程序结构(如空函数体等)
异常、捕获与finally
- raise
抛出异常对象,如raise Exception("Invalid level!", 0)
- try-except-else
except语句会在对应异常之一被触发时执行,else语句会在没有异常出现时执行try: 正常逻辑 except Exception,err: 触发自定义异常 else: 其余代码
- try-finally
finally语句会最终执行(无论是否出现异常)try: <语句> finally: <语句> #退出try时总会执行 raise
del变量定义
Python中可以通过del语句删除变量定义,则也接触了该变量引用对于值对象的引用关系
比如
a = 1
b = 2
del a,b
#下面语句报错,已经没有引用a
print(a)
模块与导入
- import
一个 Python 文件,以 .py 结尾,可以通过import语句作为一个模块导入到其他源代码中,如
则代码中可以通过模块名.成员名访问成员访问模块内部成员,如# test.py def call(): pass
import test test.call()
- reload
在一个脚本中,每个模块的全局代码只会在第一次导入时执行一次,如需再次执行可以通过reload函数,重新执行模块的全局代码,如import test reload(test)
- from…import…
通过from…import语句可以指定只从模块中导入部分成员,同时导入成员可以直接使用而无需加上模块前缀,如
同时可以使用通配符*代表导入所有成员from test import call call()
from test import * call()
集合
- 列表
list = [1,2]
- 元组
元组即只读列表,不可修改tuple = (1,2)
- 字典
dict = { 'key1':val1 , 'key2':val2 }
- set
container = {1,2} container = set() container = set(1)
垃圾回收
Python中采用实时引用计数gc和异步分代gc共同工作。
因为使用引用计数实时回收,所以性能损耗较大。
为了解决循环引用,还开启一个异步的分代gc。
面向对象
Python中的类内部方法,包含实例方法、类方法、静态方法三种
- 访问权限
通过单下划线开头定义的成员为protected成员,只能在类内部及子类内部访问
通过双下划线开头定义的成员为private成员,只能在类内部访问class A: __i = 5 _j = 6 class B(A): c = A._j print(B.c) #下面语句报错 #print(A.__i)
- 构造函数与析构函数
类内部的__init__方法为构造函数
类内部的__del__方法为析构函数
与其他语言不同的是,如果没有显示调用,Python在构造和析构时,并不会隐式调用父类的无参构造或者析构class MyClass: def __init__(self): print('init') def __del__(self): print('del') # 实例化类 x = MyClass() del x
- 实例属性与类属性
类属性为定义在类内部方法外部的属性,实例属性为在类实例方法内提供self绑定或者直接通过类实例对象绑定的属性class B: c = 5 def call(self,i): self.s = i print(B.c) b = B() b.call(999) b.x = 5 print(b.x) print(b.s)
- 实例方法
实例方法必须设置第一个形参为self来接收this对象class MyClass: i = 0 def f(self): return 'hello world' def __init__(self, _i): self.i = _i # 实例化类 x = MyClass(5) print(x.i) x.f()
- 静态方法
静态方法通过在方法上加上@staticmethod注解,标记为静态方法
静态方法可以直接通过类名调用class MyClass: @staticmethod def f(): return 'hello world' MyClass.f()
- 类方法
类方法通过在方法上加上@classmethod注解,标记为类方法。
类方法与静态方法的区别是,类方法第一个形参用于接收一个可以代表当前类的对象,使用该对象可以访问类的构造函数等功能,比如class MyClass: i = 0 def __init__(self, _i): self.i = _i @classmethod def create(cls,_i): #使用一个参数的构造函数 obj = cls(_i) return obj instance = MyClass.create(5)
- 继承
Python支持多继承,多继承。调用同名方法时,按照最左匹配原则,也就是离当前类名称最近的基类中如果存在同名方法,则使用该方法。
同时可以通过基类名称,在类内部使用基类方法,如
另一种访问基类同名成员的方法是,使用super关键字class Man: def __init__(self, name): self.name = name def call(self): print('man call') class Alive: def call(self): print('Alive call') class Stu(Alive,Man): def __init__(self, name): #调用父类构造 Man.__init__(self, name) #或者使用下面这种super写法 #super(Stu,self).__init__(self, name) stu = Stu('yyt') #ouput : Alive call stu.call()
- 抽象类
Python中的抽象类需要借助基本库里的abc模块(abstract base class)
Python中的抽象类更接近一种显示要求
通过继承abc.ABC来创建一个抽象类
类中被@abc.abstractmethod注解修饰的方法为抽象方法
其作用是
1.抽象类实例化报错
2.继承抽象类的子类如果没有重载全部抽象方法,实例化报错import abc class Foo(abc.ABC): @abc.abstractmethod def fun(self): pass #下面语句报错 a = Foo()
泛型函数
Python中的泛型函数需要借助基本库里的functools模块
被@singledispatch注解修饰的方法为泛型方法
通过@方法名.register注解修饰其他方法,标记为泛型方法的实现,并标记方法形参第一个参数的泛型
from functools import singledispatch
@singledispatch
def add(obj, new_obj):
raise TypeError
@add.register(int)
def _(obj, new_obj):
return obj + new_obj
@add.register(list)
def _(obj, new_obj):
return obj.extend(new_obj)
add(1,2)
add([1,2],[3])
多线程
Python通过两个标准库thread和threading提供对线程的支持。
Python多线程提供了两种实现方式,基于函数以及基于类的实现。
-
基于函数
thread.start_new_thread ( function, args[, kwargs] )
function - 线程函数。
args - 传递给线程函数的参数,他必须是个tuple类型。
kwargs - 可选参数。#!/usr/bin/python # -*- coding: UTF-8 -*- import thread import time # 为线程定义一个函数 def print_time( threadName, delay): count = 0 while count < 5: time.sleep(delay) count += 1 print "%s: %s" % ( threadName, time.ctime(time.time()) ) # 创建两个线程 try: thread.start_new_thread( print_time, ("Thread-1", 2, ) ) thread.start_new_thread( print_time, ("Thread-2", 4, ) ) except: print "Error: unable to start thread" while 1: pass
-
基于类
threading 模块提供的方法:- threading.currentThread(): 返回当前的线程变量。
- threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
- threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
Thread类中提供了线程实例状态相关的方法
- run(): 用以表示线程活动的方法。
- start():启动线程活动。
- join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
- isAlive(): 返回线程是否活动的。
- getName(): 返回线程名。
- setName(): 设置线程名。
#!/usr/bin/python # -*- coding: UTF-8 -*- import threading import time exitFlag = 0 class myThread (threading.Thread): #继承父类threading.Thread def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): #把要执行的代码写到run函数里面 线程在创建后会直接运行run函数 print "Starting " + self.name print_time(self.name, self.counter, 5) print "Exiting " + self.name def print_time(threadName, delay, counter): while counter: if exitFlag: (threading.Thread).exit() time.sleep(delay) print "%s: %s" % (threadName, time.ctime(time.time())) counter -= 1 # 创建新线程 thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2) # 开启线程 thread1.start() thread2.start() print "Exiting Main Thread"
锁
threading模块中,提供Lock类(锁)和RLock类(可重入锁)。
每种锁中都有以下方法:
- acquire方法获得锁
acquire(blocking=True, timeout=-1),blocking参数表示是否阻塞当前线程进入等待,timeout表示最长等待时间 ,-1代表不限制。如果获得了锁,返回True,如果超过了超时等待时间返回False。 - release方法释放锁
import threading
rlock = threading.RLock()
rlock .lock()
rlock.realease()
@decorator与aop
Python中提供装饰器注解,可以通过注解,对函数进行aop(切面编程)
def decorator_maker_with_arguments(decorator_arg1, decorator_arg2):
print "I make decorators! And I accept arguments:", decorator_arg1, decorator_arg2
def my_decorator(func):
print "I am the decorator. Somehow you passed me arguments:", decorator_arg1, decorator_arg2
def wrapped(function_arg1, function_arg2) :
print ("I am the wrapper around the decorated function.\n"
"I can access all the variables\n"
"\t- from the decorator: {0} {1}\n"
"\t- from the function call: {2} {3}\n"
"Then I can pass them to the decorated function"
.format(decorator_arg1, decorator_arg2,
function_arg1, function_arg2))
return func(function_arg1, function_arg2)
return wrapped
return my_decorator
@decorator_maker_with_arguments("Leonard", "Sheldon")
def decorated_function_with_arguments(function_arg1, function_arg2):
print ("I am the decorated function and only knows about my arguments: {0}"
" {1}".format(function_arg1, function_arg2))
decorated_function_with_arguments("Rajesh", "Howard")
比如上述的
@decorator_maker_with_arguments("Leonard", "Sheldon")
def decorated_function_with_arguments(function_arg1, function_arg2):
.....
最终进行切面编程后,实际调用被装饰函数decorated_function_with_arguments时,会改为使用
temp = decorator_maker_with_arguments("Leonard", "Sheldon")(decorated_function_with_arguments)(function_arg1, function_arg2)
- decorator_maker_with_arguments(“Leonard”, “Sheldon”)得到my_decorator这个函数
- 接着my_decorator(decorated_function_with_arguments)得到wrapped这个函数
- 最终就是执行wrapped(function_arg1, function_arg2)
反射
- dir
dir函数不带参数时,返回当前作用域范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。
dir带参数时,将返回参数的所有属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。class A: a = 1 obj = A() print(dir(obj))
- setattr(obj,attr,val)
setattr函数,通过反射更新obj的attr属性的值为valclass A: a = 1 obj = A() setattr(obj,'a',2) print(obj.a)
- getattr(obj,attr)
getattr函数,通过反射获取obj的attr成员(属性/方法)class A: def show(self): print('show') def look(): print('look') obj = A() fun1 = getattr(obj,'show') fun2 = getattr(A,'look') fun1() fun2()
- delattr(obj,attr)
delattr函数,del对象成员class A: pass obj = A() obj.a = 5 delattr(obj,'a') print('Go ahead') #下面语句会报错 print(obj.a)
更多文章,请搜索公众号歪歪梯Club