正好最近在学python,感觉有语言基础的话更多在乎一些语法糖,毕竟其他东西在之前应该接触过了。
笔者C++是起始语言,也接触过java、js,介绍一点python的特点吧。帮助自己巩固所学,也希望能帮助别人快速上手。

一.语言本身特点

python是一门解释型语言。 解释型语言与编译型语言: 解释型语言:先翻译成中间代码,再由解释器对中间代码进行解释运行。程序不需要编译,在运行时才翻译成机器语言,每执行一次都要翻译一次。效率比较低。典型如js,相当于吃火锅,想吃啥煮啥 编译型语言:将所有源代码一次性转换成二进制指令,即生成一个可执行文件。典型如C/C++,相当于炒菜,从原材料到菜有编译过程 半解释半编译:典型如java,相当于干锅,加热到一半(半熟)然后放桌上继续加热 ![]()

Python中,万物皆对象
可变对象mutable:列表/集合/字典,自定义对象等:可以在原来地址空间进行修改
不可变对象immutable:字符串,数字int,元组等:不可以在原地址修改,而是要另辟内存空间

二.语法基础

1.标识符

区分大小写

可以用下划线、字母、数字、中文、日文……

不能用关键字

不能使用python自带函数

def func1():
    Myname=2
    myname=3
    print(myname)
    print(Myname)
    # false=True   not recommended but true
    # print(false)
    派松=4
    print(派松)
    ゆめ=7
    夢=8
    ソフトウェア=9

2.数据类型

整数可以很大,不是int的范围。 没有long和int 复数类型:用a+bj形式表示(a,b∈R) 布尔类型:是整数类型子类。返回值为False的类型:None,False,0, 0.0, 0j, ‘’,””,[],(),{}

字符串类型:
普通字符串:可以用单引号也可以用双引号包裹的字符串
原始字符串:在普通字符串前加r,转义字符无效。
长字符串:用三重单引号或三重双引号包裹的字符串,可以显示换行缩进等字符。

def func3():
    print('abc') #abc
    print("def") #def
    print('''xxx''') #xxx
    s="""a
    bc
    def
        ghi
    """
    print(s)
    #a
    #bc
    #def
    #    ghi
    
    a=r'\u0048'
    b='\u0048'
    c="yyy\\yyy"
    print(a) #\u0048
    print(b) #H
    print(c) #yyy\yyy

.format用法

def func4():
    name="tom"
    age=30
    print(name+' is '+str(age)) #tom is 30
    s1='age is {0}'.format(age) 
    print(s1)  #age is 30
    s2='{0}\'s age is {1}'.format(name,age)
    print(s2) #tom's age is 30
    s3='{n}\'s age is {a}'.format(n=name,a=age)
    print(s3) #tom's age is 30

    money=1234.554
    print('{0}今天收入是{1:f}元。'.format(name, money)) #tom今天收入是1234.554000元。
    print('{0}今天收入是{1:.2f}元。'.format(name, money))  #tom今天收入是1234.55元。
    print('{0}今天收入是{1:g}元。'.format(name, money)) #tom今天收入是1234.55元。
    print('{0}今天收入是{1:e}元。'.format(name, money)) #tom今天收入是1.234554e+03元。

可通过int(),str(),bool()完成相互转换

3.运算符

特殊的:

/ 正常除法

** 幂

// 整数除法
逻辑运算(虽然C++后来标准也支持这些英文单词)

  • not 非
  • and 与
  • or 或

没有三元运算符?:
采用 expression if judgement else expression2 来替代

x=5
print("great" if x>3 else "bad") #great
x=2
print("great" if x>3 else "bad") #bad

同一性测试运算符:判断两个对象是否是一个对象,即判断id

def func4():
    a=257
    b=257
    print(id(a))
    print(id(b))
    print(a is b)
    c=1234567812345678
    d=1234567812345678
    print(c is d)

4.控制语句

不习惯的地方:

  1. 判断语句不用括号
  2. 判断语句结束加:
  3. 不用大括号而用缩进表示代码块
  • 分支语句
if judgement1:
  expression1
  if judgement4:
    expression4
    experssion5
elif judgement2:
  expression2
else :
  expression3

没有switch!

  • 循环语句
    python没有do while
    python在循环后新增了else,当循环正常退出时将进入else(如果遇到break,return,异常时将不进入else)
  1. while
while judgement :
  expression1
  expression2
while judgement :
  expression1
  expression2
else :
  expression3
  1. for
for .. in .. :
  expression1
  expression2
for .. in .. :
  expression1
  expression2
else:
  expresssion3

range()

  • range(x)表示[0,x-1)
  • range(start,stop)表示[start,stop),以步长为1进行遍历
  • range(start,stop,step)表示[start,stop)并以step步长遍历
def func17():
    for x in range(6):
        print('{0} '.format(x),end="")  #0 1 2 3 4 5
    print()
    for x in range(0,6):
        print('{0} '.format(x),end="")  #0 1 2 3 4 5
    print()
    for x in range(0,6,2):
        print('{0} '.format(x),end="")  #0 2 4

5.函数

通过def关键字来定义函数

def function_name(params):
  expression1
  expression2
  return ret #can be omitted

关键字参数:使用形式参数的名字来确定输入的参数值。
可以采用关键字参数调用函数,但使用关键字参数后,之后的参数也必须使用关键字参数
函数参数可以有默认值,但有默认值的参数必须放在最后

不定长参数
*可变参数:被组装成元组 不是最后一个参数时,后面的参数需要用关键字参数形式传递
**可变参数:被组装成字典 必须放在所有参数最后

可变参数/**可变参数不能由已有变量传递,需要通过/**进行拆包才能进行传递。

def func12(*sum,multiple=1.0):
    total=0.0
    for num in sum:
        total+=num
    print(total*multiple) 
func12(2,3,4)
tp=(3,4,5) #12
#func12(tp) #wrong
func12(*tp)
func12(1,2,*tp) #15

变量作用域
函数内创建,即为函数的局部变量,优先级更高
使用global关键字可修改全局变量

函数嵌套
函数可以嵌套
内部函数可以访问外部函数变量
外部函数不能访问内部函数变量
内部函数不能被外部函数以外的地方访问

x = 20
def print_val():
    x=15
    print("函数中x = {0}".format(x))

def print_value():
    global x
    print("函数中x = {0}".format(x))
    x = 10
    print("函数中x = {0}".format(x))

print_val() #15
print_value() #20 10 
print("全局变量x = {0}".format(x)) #10

6.类

class关键字

class ClassName:
class ClassName:
  def __init__(self,param1,param2):
    self.attribute1=param1
    self.attribute2=param2

对象实例变量
存储描述对象的状态特征的值
在内部通过self.变量名访问
在外部通过对象名.变量名访问
对象构造完后,还可以为对象增添属性

类变量
所有实例都共有的变量
在内部通过self.变量名方法
在外部通过对象名.变量名访问
类变量一直存储在内存中。
用对象名.变量名修改类变量时会增加一个同名的实例变量。
__dict__查看所有实例变量

对象构造完后,可以为对象增加实例变量
修改对象的类变量不会修改类的类变量值,只会修改该对象的类变量值
一个类只能有一个构造函数
用对象名.变量名修改类变量时会增加一个同名的实例变量。

实例方法
普通方法,属于对象所有的
第一个参数必须是self

类方法
特殊方法,属于类所有的
第一个参数必须是cls
只能访问类变量和其他类方法
使用@classmethod装饰
类似于java的static方法

静态方法
不属于类/对象
只是需要一个类作为依托
采用@staticmethod装饰
C++/JAVA的静态方法指之前的类方法
python的静态方法不能访问类里的内容,只是挂号方法

class Account:
    rate=0.06
    def __init__(self,owner,amount):
        self.owner=owner
        self.amount=amount
    
    @classmethod
    def calc(cls,amt):
        return cls.rate*amt
    
    @staticmethod
    def interest(amt):
        return Account.calc(amt)

acc=Account("tom",10000)
# print(acc.calc(10000)) #wrong
print(Account.calc(10000)) #600.0
print(acc.interest(11000)) #660.0
print(Account.interest(12000)) #720.0

什么都不做的类,pass
name 获取类的名称
module 获取类的模块
bases 获取类的所有父类
dict 获取类的所有属性和方法

信息隐藏
私有类变量: 在变量名字前面增加__
私有实例变量:在变量名字前面增加__
私有实例方法:在方法前面增加__
在类内部访问该私有成员时也需要加上__,即self.__
外界无法直接访问私有成员
但是可以通过_类名__变量名访问私有变量
但是可以通过_类名__方法名访问私有方法
Python封装性主要靠程序员自觉(python的私有成员还真是公开啊~)

class Circle():
    def __init__(self,r):
        self.__radius =r
    def getArea(self):
        return math.pi*self.__radius*self.__radius
    
    def test1(self):
        # self.hidden() #wrong
        self.__hidden()
        print("this is a test")

    def __hidden(self):
        print("hidden")

    @classmethod
    def expand(cls,times):
        print("cls")
        # return getArea()*times #wrong:cannot get getArea
        return times

def func2():
    circle=Circle(3)
    # print(circle.radius) #wrong
    # print(circle.__radius) #wrong
    circle._Circle__hidden() #hidden
    print(circle._Circle__radius) #3
    circle.test1() #hidden this is a test
    print(circle.expand(3)) #cls 3

可以像java一样使用get和set方法来访问变量达到封装效果。

@property
def variable_name(self):
    return self.__variable_name

@variable_name.setter
def variable_name(self,variable_name):
    self.__variable_name=variable_name

有了上述定义后,可以使用obj.variable_name访问属性,用obj.variable_name=value修改属性值

类继承
子类继承父类所有成员变量和方法,除了私有部分
如果子类有构造函数,则默认不自动调用父类构造函数
如果子类没有构造函数,在创建子类对象时会自动调用第一个父类的构造函数(相同参数列表)
如果有多继承,采用MRO算法,从父类开始,深度优先,从左到右,除了pass以外,碰到的第一个父类构造函数,参数列表吻合,就创建。如果不吻合,就报错。
使用super()可以调用父类所有的东西

多态
允许重写方法。需要子类方法名和父类的方法名相同,参数列表相同
子类对象转型为父类,但实际上执行是自身的方法
isinstance(obj_name,class_name)方法可以判断对象是否属于某个该类
issubclass(class1,class2)方法可以判断class1是否是class2的子类

object类是所有类祖宗
__str()__方法:输出描述信息
__eq()__方法:对象比较方法
内存地址相同则相同,不一样再比较eq方法

枚举类
管理一组有限个常量的集合,需要import enum
@enum.unique 装饰器,保证成员取值不同

7.数据结构

  • 序列:可迭代,元素有序,可以重复出现
  • 集合:可迭代,元素无序,不能重复出现
  • 字典:可变可迭代的K-V对
  1. 序列:可迭代、有序、可重复

列表 list 列表:可变的序列,使用[]创建,逗号分隔

  • 追加元素 list.append(element)
  • 追加列表 list.extend(list2)
  • 插入元素 list.insert(element)
  • 替换元素 list[i]=element
  • 删除元素 list.remove(x) 从左到右,只删除第一个
list.pop(i)    删除第i个,并返回
del list[i]    删除第i个
  • reverse:将列表反转
  • copy:拷贝
  • clear:清空
  • index:返回x元素所在的位置
  • count:返回x出现的次数

字符串 str
元组 tuple 元组:不可变的序列,使用()创建,逗号分隔。不存在单元元组,当元组只有一个元素时会被认为是该元素的类型。
范围 range
字节序列 bytes
序列可以进行的操作:索引、分片、加和乘

  1. 集合:无序,不能重复,逗号隔开,用{}包围
    创建空集合,用set()
    add(elem) 增加一个元素
    remove(elem) 删除元素,如果不存在,则报错
    discard(elem) 删除元素,如果不存在,不报错
    pop() 删除返回任一元素
    clear() 清除集合
    不可变集合:frozenset
  2. 字典:可变可迭代的数据结构,K-V对
    {key1:val1, key2:val2, key3:val3}
    采用dict()创建
    get(key) 返回这个key对应的value
    items() 返回字典的所有键值对
    keys() 返回所有keys
    values() 返回所有的values
    采用for循环进行遍历
    s={}创造的是空字典而非空集合

8.模块

导入方式

import module_name
import module_name as new_name
import module_name1, module_name2
from module_name import function_name,variable,class_name

import module_name 会导入模块所有代码元素,访问时需要加module_name.
from module_name import function_name,variable,class_name 导入模块特定元素,访问时不需要加module_name

导入模块的搜索顺序,是按照sys.path变量值搜索路径:
当前目录\(\rightarrow\)Python安装目录\(\rightarrow\)PYTHONPATH环境变量
添加路径方式:
①临时添加:使用sys.path.append(“xxx”)临时添加路径
Python解释器重启后无效
②永久添加:在Python安装目录或者Lib\site-packages目录新建xx.pth
在xx.pth中,每行一个路径
③使用PYTHONPATH环境变量添加,多个路径用分号隔开

9.包

把功能相近的模块文件放在同一个目录下,就是包Package

  • 这个目录必须有一个__init__.py文件
  • init文件内容可以为空,也可以设置__all__的值用于限定导入范围
  • 包可以包含子包,没有层级限制
  • 每个子包都必须包含一个__init__.py文件
  • 包可以有效避免模块命名冲突

包的导入和调用

import package1.sub_package1.module1_1
from package1.sub_package1 import module1_1
from package1.sub_package1.mudule1 import func1
from 包名 import *
#可以使用相对路径
from . import module1_2
from .. import sub_package2
from .. sub_package2 import module2_1


库:library,具有相同功能模块的集合,本质上还是包和模块,方便他人引用

异常
BaseException: Python异常总祖宗
Exception
ArithmeticError
StopIteration
Warning
RuntimeWarning


SystemExit
……

捕获异常

try:
    expression1
    expression2
except error_type1:
    expression3
except error_type2:
    expression4
else:
    expression5
finally :
    expression6

大异常写下面,小异常写上面
可以使用使用traceback.print_exc查看错误堆栈信息
else 提供了更细粒度控制,也可以没有
finally可以没有,但不管try,except结果如何,必须执行finally

with open(filename) as file:
    expression1
    expression2

with…as语句 可以自动释放资源,推荐使用

自定义异常
继承Exception类或者子类
提供一个字符串参数的构造函数

class MyException(Exception):
    def __init__(self,message):
        super().__init__(message)

显式抛出异常:可以使用raise语句主动抛出异常
raise MyException('...')

常用的模块和库

Python提供math模块进行基础数学运算
math.ceil(x): 返回大于等于x的最小整数
math.floor(x): 返回小于等于x的最大整数
math.round(x): 对x进行四舍五入
math.log(a, base): 返回以base为底,a的对数
math.sqrt(a): 返回a的平方根
math.pow(a,b): 返回a的b次方

随机数模块提供一些随机数函数
random.random():返回[0,1)之间的小数
random.randrange(stop):返回[0,stop)步长为1的随机整数
random.randrange(start.stop[,step]):返回[start,stop)之间步长为step的随机整数
random.randint(a,b):返回[a,b]之间的随机整数

datetime模块
datetime类:datetime类需要用datetime.datetime.function_name()来调用
datetime(year, month, day, hour=0,minute=0,second=0, microsecond=0, tzinfo=None), microscond微秒
datetime.today(): 返回此刻日期和时间
datetime.now(tzinfo): 返回指定时区的此刻时间和日期,如tz未指定,等同于today()
datetime.utcnow(): 返回当前utc日期和时间
datetime.fromtimestamp(timestamp, tz=None):返回与UNIX时间戳对应的本地日期和时间, 1970-01-01 00:00:00开始
datetime.utcfromtimestamp(timestamp):返回与UNIX时间戳对应的UTC日期和时间
datetime.timedelta(days, seconds, microseconds, milliseconds, minutes, hours, weeks) 所有参数都是可选的,可以是正数负数
datetime.strftime(format)(比如'%y-%m-%d')

字符串其他功能
下标和切片:a[2], a[-1], a[:5], a[2:5]
包含:in 和 not in
大小写:upper(), lower(), isupper(), islower()
isalpha(): True, 如果字符串只包含字母,并且非空
isalnum(): True,如果字符串只包含数字字母,并且非空
isdecimal(): True,如果字符串只包含数字,并且非空
startswith(a) 和 endsWith(a):以某某开头,或者某某结尾

字符串其他功能
字符列表拼接:join, 将列表中多个字符串连起来
字符串分裂:split, 将一个大字符串分裂为多个字符串
文本居中: center()
对齐文本: ljust(), rjust
去除字符串两头的空格:strip(), lstrip(), rstrip()
查找字符串,并返回位置索引,如果找不到,返回-1
index(), 找不到报异常
find(),找不到不报异常
替换字符串:replace(str1, str2)

Python提供copy模块,可生成新的拷贝
copy.copy()浅复制 会跟着原对象变
copy.deepcopy()深复制,包括深层次的嵌套 不会跟着原对象变
is 比较两个对象内存地址是否相等
==比较内容是否相等,调用__eq__()方法

文件读写

文件系统是由OS管理的
文件系统和Python程序/进程是平行的
文件系统是由文件夹和文件递归组合而成
文件目录分隔符
Linux/Unix 用/隔开
Windows用\隔开。在程序中可以用/或\代替
文件包括文件里面的内容和文件属性
文件属性:名称、大小、扩展名等

Python使用os模块进行文件系统管理
os.rename(src, dst): 将src文件名字修改为dst
os.remove(path): 删除文件,如果删除目录,引发异常
os.mkdir(path): 创建新目录,如果存在,引发异常
os.rmdir(path): 删除目录,如果目录非空,引发异常
os.walk(top): 遍历top所有子目录,自顶向下,返回一个三元组
os.listdir(dir): 列出指定目录下的所有文件和子目录
os.curdir: 当前目录
os.pardir: 上一级目录

Python提供了os.path模块对文件路径进行管理
os.path.abspath(path): 返回path绝对路径
os.path.basename(path): 返回path的基础部分
os.path.dirname(path): 返回path中的目录部分
os.path.exists(path):判断path是否存在
os.path.isfile(path): 判断path是否是文件
os.path.isdir(path): 判断path是否是目录
os.path.getatime(path): 返回文件最后访问时间戳
os.path.getmtime(path): 返回文件最后修改时间戳
os.path.getctime(path): 返回文件创建时间戳
os.path.getsize(path): 返回文件大小,以字节为单位

文本文件读写
read(size=-1):读取size个字符,-1表示不限,下同
readline(size=-1):读取单行字符
readlines(hint=-1):读取每一行到一个列表中,hint表示行数
write(s):将s写入到文件中
writelines(lines):向文件写入一个列表,不添加分隔符
flush():刷新缓存区,写入到文件中

| |文件读写 |读 |写
| ---- | ---- | ---- |
| | | |