Python3基础复习

基本语法

基本语法只列举与Java不一样的。

运算符

and, or而非 &&, ||,另外还有not

/相当于java的double除法,**相当于java的Math.pow(a, b)

0、空字符串、列表、元组等都可以返回False

位运算符:~相当于java的

输出格式

print('%s%d%f'%(stringVar, intVar, floatVar), end = ' ')

数据类型

  • str""
    • 切片[起步:结束:步长]
    • 常用函数:find不存在返回-1, index不存在会报错, count(str, start, end), replace(str1, str2, count), split, startswith, upper, ljust, center, partition, strip, join, isalnum(字母或数字), isalpha
  • list[]
    • 同样通过[index]取值,但没有切片
    • 常用函数:append, insert, pop(index), remove(content), count, extend(集合), index, reverse, sort, clear, copy
  • tuple():元素不可变
    • 切片
  • dict
    • 对key赋值时如果没有该key就是添加
    • 常用函数:get(key, default), keys(), values(), items()用于遍历dict,如for k, v in dict1.items()

内置函数,类似static func:del()真的在内存中删去, in, not in, len, max字符串/列表都可以, list, tuple, type, id查内存位置, isinstance(var, varType)也可以 isinstance(var, (varType1, varType2)), abs, sorted(list, reverse), sum(list), round(float, digit), eval("str num expression")

集合可以解包赋值,即a,b,c = [1,2,3]

推导式

# list推导式,返回list
variable = [func(parm) for parm in iterableObj if parm == 2]
resList = [squared(i) for i in range(10) if i % 3 is 0]

# dict推导式
# 聚合
mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
mcase_frequency = {
    k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0)
    for k in mcase.keys()
    if k.lower() in ['a','b']
}
#  Output: {'a': 17, 'b': 34}
# 交换kv
mcase = {'a': 10, 'b': 34}
mcase_frequency = {v: k for k, v in mcase.items()}

# tuple推导式
squared = {x**2 for x in [1, 1, 2]}
# Output: set([1, 4])

生成器的()方式很类似,详细看函数部分的生成器下面。

数据结构

list里面存储的实际上是指针。

拷贝:list、dict可变,另外三个不可变

浅拷贝:list2 = list1[:]或list1.copy(),只是新建了一个list存储新指针,但指针都是指向原来的对象。如果改变其中一个list的指针不会影响另外一个,即list[index] = xxx。但如果指针指向的对象被修改,两者都会受影响,即a = xx, list[a, ...], a[index] = xxx。

深拷贝:import copy,然后copy.deepcopy(),如果数据类型不可变,那指针仍指向原对象;如果可变,则会复制可变对象,指向新的可变对象。

函数

可变对象和不可变对象:可变对象作为参数时,传入的是本体。不可变对象作为参数时,传入的是副本。在函数里无法对函数外的指针进行重定向(除非用global,但最好不用),只能对传入的可变对象进行修改。

参数类型:位置参数、默认参数、关键字参数、可变参数

默认参数:def func(parm1, parm2=2):默认参数放到右边

关键字参数:func(parm2=a, parm1=2)实现参数顺序的变化,但关键字只能全写或者不写(除非设置默认参数)

可变参数(都是可选参数,即设置了可以不给):

  • def func(*args):,调用func(a, b, c), func(a)传入的参数会变为tuple,其指针为args。

  • def func(**kargs):,调用func(a = 1, b = 2),参数作为两个kv传入kargs的dict中

  • 反过来,def func(a,b)可以解包调用args=(1,2), func(*args)**kargs一样可以。

混合使用:先位置参数,默认参数,包裹位置,包裹关键字(定义和调用都应遵循)

# 简单来说,对于后面的可变参数,a,b...的输入会被归入*args,a=b的关键字参数会被归入**kargs
def func(name, age, sex=1, *args, **kargs):
    print name, age, sex, args, kargs
# func('a', 25, 2, 'music', 'sport', class=2)
# a 25 1 ('music', 'sport') {'class'=2}

返回值

返回可以结果可以是多个参数,会被包裹在tuple内。返回没有类型限制。

生成器/迭代器

含有yield的函数就不是一般的函数了,而是生成器。调用一次next就执行到yield时暂停(不调用不执行),再调用就在暂停处继续。如果跳出循环,不再遇到yield,那么next会报错。利用for i in iterableObject:更方便,即便最后一次没有yield(执行函数剩余部分)也不会报错。生成器能避免一次性生成一个大的数据集。

其他写法

a = (x for x in range(10)) # 同样调用一次next(a)执行一次
a = [x for x in range(10)] # 一次性生成10个数的list
tmp = yield i #不能赋值,除非在函数外加上下面的send,但send之前需要调用过一次next。这样i会变为11,并能够赋值给tmp。send同样可以启动一次迭代。
a.send(11)

# 创建迭代对象。for a in b中,b需要是迭代对象,之前提到的集合都属于。
it = iter(list)

lambda

Java的lambda需要特定的函数才能使用。

s = lambda x: x*2
s(10) # 相当于x=10,然后10*2
# 其他形式
s = lambda : "xxx"
s = lambda x, y: x+y
# 三元运算,parm1, parm2: 成立的返回值 if 判断条件 else 不成立的返回值
s = lambda x, y: x if x > y else y

高级函数

new_list = map(lambda x:x*2, old_list) # 返回map对象,可遍历
new_list = map(lambda x, y:x*y, old_list1,old_list2)
new_list = filter(lambda x:x>2, old_list) # 返回filter对象
new_list = reduce(lambda x, y:x+y, old_list, Optional(initialVar)) # 需要from functools import reduce

阅读理解

sorted(dic.items(), key = lambda x:x[1], reverse=True) # 根据值排序
list1 = [{key1:val1, key2:val2},
         {key1:val3, key2:val4}
        ]
sorted(list1, key = lambda x:x[key2], reverse=True) # 根据字典的某个key的值排序

面向对象

import datetime, re

DATE_PATTERN = re.compile('^\d+\-\d+\-\d+$')

def str_to_date(date):
    if isinstance(date, datetime.date):
        return date
    elif isinstance(date,str) and DATE_PATTERN.match(date):
        return datetime.date(*map(int, date.split('-')))
    raise TypeError


class Person():
    '''
    	doc
    '''
    
    # 相当于java的static成员变量
    life = True 
    
    def __init__(self, name, birthday, age):
        self.name = name
        self.birthday = birthday
        self.__age = age # 私有属性,通过实现getter来查看。但其实可以强制访问
        
    @property
    def birthday(self):
        return self._birthday
    
    @birthday.setter
    def birthday(self, birthday):
        self._birthday = str_to_date(birthday)
    
    @property
    def age(self):
        return datetime.date.today() - self.birthday
    
    def __str__(self):
        return '%s,%s(%s)'%(self.name,self.birthday, self.age)
    
    # 静态和类方法都可以通过类或实例调用,都不能够使用实例属性和方法。静态方法不需要参数,类方法至少有cls参数
    @staticmethod
    def func1(): 
        do something # 用Person.类属性访问
        
    @classmethod
    def func2(cls): 
        do something # 用cls.类属性访问
    


person = Person('Xiao Ming','1980-10-1')

print(person)
 
person.birthday = '1981-1-2'

print(person)

person.birthday = datetime.date(1979,12,12)

print(person)

person.birthday = '123456' # raise TypeError

class chinese(Person):
    def __init__(self, name, birthday, province):
        super().__init__(name, food)
        self.province = province

内置类方法

person.__dict__ # 将属性变为dict
person.__doc__ # 文档信息
# 一般从下面这条代码后才开始写运行的代码,相当于java的main方法。否则被import时会执行不必要的代码。因为__name__在其他py文件中被调用时就变为了调用py文件的名字了
if __name__ == '__main__': 

多继承

class A():
    def a():
        print("A,a")
        
class B():
    def a():
        print("B,b")
        
class C(A,B):
    def c():
        print("C,c")
        
c = C
c.a # 会调用A的方法(多继承中从左到右找)

补充

异常

try:
    do something
except exceptionName:
    do something
except Exception:
    do something
else: # 无错误
    do something
finally:
    do something

模块和包

模块

import time # 模块,相当一个文件夹。
time.sleep(5)
from time import sleep / *
sleep(5)
import pandas as pd

# 同一模块直接import pyname
import a.b # 导入统一模块下的a模块的b.py
from a import b # 同上

import sys 
print(sys.path) # 查看模块搜索路径,第一个为当前
sys.path.append('..//') #添加上一层的相对路径,这样就可以import上一层的模块了
dir() # 查看当前模块有哪些变量、模块、函数等
dir(moduleName) # 查看模块

import imp
imp.reload(modelName)

目录中只包含一个叫__init__.py的文件时才被认为是包

# __init__.py的内容
__all__ = ['pyname1', 'pyname2'] # 允许导入的模块

文件

# mode : r只读,不存在提示错误;w只写,create or overwrite;a追加;a+读写,光标移到末尾
with open(path, mode, encoding='utf-8') as file:
	content = files.read(charNum) # readlines()
    
with open(path, mode, encoding='utf-8') as file:
	content = files.write(strContent) # 只接受str,需手动换行write('\n')
    
import os
print(os.getcwd()) # 当前路径
os.listdir(path)
os.path.isfile(path) # exists(), split()将目录和文件分开列出

时间

import time
timeTuple = time.localtime(TimeStamp)
timestamp = time.mktime(TimeTuple)
timestamp = time.time()
formattedTime = time.strftime('%Y-%m-%d %H:%M:%S', timeTuple)
timeTuple = time.strptime(strTime, '%Y-%m-%d %H:%M:%S')

# 三天前时间戳
now_ts = time.time()
three_age_ts = now_ts - 60*60*24*3

线程和进程

python不支持真多线程

import threading
t1 = threading.Thread(target=funcName, args=(parms,)) # threading.Thread都是子线程
t1.start()
t1.join(timeout)
t1.setDaemon(True) # 主线程结束杀死子线程

# Lock
lock = threading.Lock
lock.acquire()
try:
    do something
finally:
    lock.release()
    
import multiprocessing
p1 = multiprocessing.Process(target=funcName, args=(parms,)) 
p = multiprocessing.Pool(num)
for i in range(5):
    p.apply(func, args=(i,)) # 串行,线程一个一个创建
    p.apply_async(func, args=(i,)) # 并行,线程一次性创建
p.close

参考:

python的各种推导式(列表推导式、字典推导式、集合推导式)

posted @ 2019-01-19 22:44  justcodeit  阅读(282)  评论(0编辑  收藏  举报