Jiahong的个人博客

凡事预则立不预则废


  • Home

  • Tags

  • Archives

  • Search

Python——命名规范

Posted on 2018-09-27

Python命名规范(Name Convention)
Reference: https://blog.csdn.net/real_myth/article/details/68927665


命名:

module_name, package_name, ClassName, method_name, ExceptionName, function_name, GLOBAL_VAR_NAME, instance_var_name, function_parameter_name, local_var_name.


应该避免的名称

  • 单字符名称, 除了计数器和迭代器.
  • 包/模块名中的连字符(-)
  • 双下划线开头并结尾的名称(Python保留, 例如__init__)

命名约定

  • 所谓”内部(Internal)”表示仅模块内可用, 或者, 在类内是保护或私有的.
  • 用单下划线(_)开头表示模块变量或函数是protected的(使用import * from时不会包含).
  • 用双下划线(__)开头的实例变量或方法表示类内私有.
  • 将相关的类和顶级函数放在同一个模块里. 不像Java, 没必要限制一个类一个模块.
  • 对类名使用大写字母开头的单词(如CapWords, 即Pascal风格), 但是模块名应该用小写加下划线的方式(如lower_with_under.py). 尽管已经有很多现存的模块使用类似于CapWords.py这样的命名, 但现在已经不鼓励这样做, 因为如果模块名碰巧和类名一致, 这会让人困扰.

引号

  • 自然语言使用双引号(想表达人为意思的,比如log,错误,提示等)
  • 机器标识使用单引号(比如dict的key等)
  • 正则表达式使用原生的双引号 r”…”
  • docstring使用三双引号

Python之父Guido推荐的规范

Type Public Internal
Modules lower_with_under _lower_with_under
Packages lower_with_under
Classes CapWords _CapWords
Exceptions CapWords
Functions lower_with_under() _lower_with_under()
Global/Class Constants CAPS_WITH_UNDER _CAPS_WITH_UNDER
gobal/Class Variables lower_with_under _lower_with_under
Instance Variables lower_with_under _lower_with_under (protected) or __lower_with_under (private)
Method Names lower_with_under() _lower_with_under() (protected) or __lower_with_under() (private)
Function/Method Parameters lower_with_under
Local Variables lower_with_under

Python——np.nan, None的判断和比较

Posted on 2018-09-26

Python值的判断与比较: np.nan, None


None

1
2
3
4
5
6
7
8
type(None)
# Output: <type 'NoneType'>

None is None
# Output: True

None == None
# Output: True

np.nan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type(np.nan)
# Output: <type 'float'>

np.nan == np.nan
# Output: False

np.nan is np.nan
# Output: True

np.nan != np.nan
# Output: True

np.nan > np.nan
# Output: False

np.nan < np.nan
# Output: False

np.nan 与 None

1
2
3
4
5
6
7
8
None == np.nan
# Output: False

None != np.nan
# Output: True

None is np.nan
# Output: False

与数字的比较

1
2
3
4
5
6
7
8
np.nan > 10
# Output: False

np.nan < 10
# Output: False

np.nan == 10
# Output: False

总结

  • 【Python2和Python3表现相同】
    np.nan 只有在np.nan != np.nan或者np.nan is np.nan时为True, 其他情况下和数字比较(包括和自身)都为False
  • 【Python2和Python3表现相异】
    Python3与Python2在直接使用np.nan时表现正常,但是当涉及到DataFrame的NaN时表现不同

特殊情况

DataFrame中的NaN与数字比较时会出现有时候为True有时候为False的情况

  • 这种情况出现在Python3中,当NaN 与数字比较时
    • 此时对于列属性类型为数值型,那么返回False
    • 否则返回True
  • Python2中NaN和数字的就是np.nan和数字比较的结果,都为False

Python2与Python3比较

  • 代码示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Python3:
import pandas as pd
df = pd.DataFrame([['a',2,3], ['a',3,4], ['a',8,9]], index=['a', 'b', 'c'])
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f'])
print(df)
# Output:
0 1 2
a a 2.0 3.0
b a 3.0 4.0
c a 8.0 9.0
d NaN NaN NaN
e NaN NaN NaN
f NaN NaN NaN

print(df > 5)
# Output:
0 1 2
a True False False
b True False False
c True True True
d True False False
e True False False
f True False False

print(df.values)
# Output:
[['a' 2.0 3.0]
['a' 3.0 4.0]
['a' 8.0 9.0]
[nan nan nan]
[nan nan nan]
[nan nan nan]]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Python2:
import pandas as pd
df = pd.DataFrame([['a',2,3], ['a',3,4], ['a',8,9]], index=['a', 'b', 'c'])
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f'])
print(df)
# Output:
0 1 2
a a 2.0 3.0
b a 3.0 4.0
c a 8.0 9.0
d NaN NaN NaN
e NaN NaN NaN
f NaN NaN NaN

print(df > 5)
# Output:
0 1 2
a True False False
b True False False
c True True True
d False False False
e False False False
f False False False

print(df.values)
# Output:
[['a' 2.0 3.0]
['a' 3.0 4.0]
['a' 8.0 9.0]
[nan nan nan]
[nan nan nan]
[nan nan nan]]

Python——位运算与逻辑运算和C++有什么不同

Posted on 2018-09-26

参考链接: https://blog.csdn.net/weixin_39129504/article/details/85958295


位运算(与C++相同)

按位与 &

按位或 |

按位异或 ^

按位取反 ~

移位运算 >>,<<,<<=和>>=


逻辑运算(与C++不同)


逻辑与

  • Python: and
  • C++: &&

逻辑或

  • Python: or
  • C++: ||

逻辑非

  • Python: not
  • C++: !

Python——函数返回值是copy还是引用

Posted on 2018-09-26

Python中有些函数是直接操作当前对象的,有些函数是操作副本的


操作当前对象的

  • list.sort(), 返回空
  • random.shuffle(my_list), 返回空
  • func(inplace=True), 这里Pandas库中的其他方法几乎均适用

返回copy的

  • 除了numpy的reshape()外目前默认都为
  • sorted(), 内置函数,返回新对象,不论接受什么参数返回的都是列表
  • np.ndarray.reshape() 返回新对象,但是新对象除了shape属性外,数据属性是和原始对象共享的
    • np.ndarray存储着数据和一个shape属性
    • 我们可通过修改shape属性而不是创建新对象来修改当前对象的shape object.shape = 3,4
    • 使用reshape时可以理解为创建了一个新对象,但是共享了数据,两个ndarray对象有相同的数据引用
    • numpy包没有array类,只有ndarray类,array是一个函数,用于构造ndarray,也可以用ndarray函数构建,但是不推荐,测试ndarray函数发现用法很奇怪

Python——标准输入input函数

Posted on 2018-09-26

本文简单讲解input和raw_input函数的用法,两者都是内置函数,无需用户自己导入模块


input函数

  • 用法

    1
    input[[prompt]]
  • 实例

    1
    2
    3
    while True:
    a = input("input: ")
    print type(a), a
  • 交互结果

    1
    2
    3
    4
    5
    6
    7
    8
    input: 123
    <type 'int'> 123
    input: "abc"
    <type 'str'> abc
    input: 1.0
    <type 'float'> 1.0
    input: abc
    SyntaxError: unexpected EOF while parsing
  • 总结:

    • 当输入为整数时,识别为int和long类型
    • 当输入为小数时,识别为float等类型
    • 当输入为string(两边需要添加")时,识别为str类型
    • 当输入为未知,像是string但是没被"引用起来时,抛出语法错误异常

raw_input函数

  • 用法与inputx完全相同

  • 把所有的输入都当做字符串,注意,如果输入的字符串带有",那么"会被保留在字符串内部

  • 用法实例

    1
    2
    3
    while True:
    a = raw_input("input: ")
    print type(a), a
  • 交互结果

    1
    2
    3
    4
    5
    6
    7
    8
    input: 123
    <type 'str'> 123
    input: "abc"
    <type 'str'> "abc"
    input: 1.0
    <type 'str'> 1.0
    input: abc
    <type 'str'> abc

Python——编程笔记,各种易忘点总结

Posted on 2018-09-26

Python编程笔记,各种易忘点总结
持续更新


快速排序和归并排序参数不可使用list子列表

  • 注意使用子列表时是一个新对象,操作子列表与原始list无关
  • 在快速排序和归并排序中不可将子列表传入,以期待可以从函数中修改原始列表的值

list初始化

1
2
l = [0] * 10
l = [0 for _ in range(10)]

list.count函数的应用

1
2
3
4
l = [1, 3, 2, 3, 3, 3]
print l.count(3)
# output:
4

str是一个不可变对象

1
2
3
4
5
6
s = "12345"
# OK
print s[1]
print s[2:4]
# Error
s[1] = 10

Random的应用

1
2
import random
print random.randint(start, end)
  • 输出一个[start, end]之间(包括start和end)的随机数

sorted函数不修改原始数组

  • sorted函数不修改原始数组
  • a.sort()会修改原始数组
    1
    2
    3
    4
    5
    6
    7
    8
    l = [1,3,4,2]
    l1 = sorted(l)
    print l, l1
    l.sort()
    print l
    # output
    [1,3,4,2] [1,2,3,4]
    [1,2,3,4]

sorted参数cmp和key比较

  • key是个单参数函数,返回值为一个可用于比较的值即可
  • cmp是个双参数函数,返回值为-1, 1, 0,分别表示小于,大于,等于
    • 特别注意不是返回True和False
  • 二者均可作为排序的比较函数

Python数值类型自动转换

  • 强制类型转换: int(a)
  • 隐式转换
    • boolean 型转int型: True =1 False =0
    • 自动类型提升: int型转float型
    • 注意: 两个int型的除法不会保留小数,这点与C++一致

关于bool

  • if判断语句中,实际上时调用bool(object)
  • bool(object)调用的时object.__bool__()
  • 如果一个对象没有实现__bool__方法,那么会尝试调用__len__方法
    • 返回为0时表示False
    • 否则返回True

对象ID

  • Python中对象的ID类似于其他语言中对象的地址
  • 调用方法为
    1
    2
    id(object)
    # Output: 4332312578

运算符号的内部实现

  • + 和 +=
    • +: add()
    • +=: iadd()
      • 当没有iadd()时Python解释器会调用add()
  • * 和 *=
    • *: mul()
    • *=: imul()
      • 当没有imul()时Python解释器会调用和mul()
  • 不可变变量,比如tuple也可以调用*=和+=,表现也是一样的,只是对象id会改变,等价于调用了__add__()然后又赋值给当前变量*
    1
    2
    3
    4
    tu1 = (1,2,3)
    tu2 = (2,3,4)
    tu1 += tu2 # <==> tu1 = tu1 + tu2, id of tu1 will change
    # Output: (1,2,3,2,3,4)

尽量避免使用最小整数

  • 需要初始化一个最小值,然后方便求得某个序列的最大值,此时可以初始化为某个可能的值,从而避免寻找最小整数的尴尬,可能会找错,初始化错的话很容易造成后面结果都错

参数”key“

一些需要比较功能的函数都会有此参数

  • key参数是一个函数,这个函数接受一个唯一的对象,然后返回用于比较的值,外层函数比较时会使用key函数返回值进行比较
    • 比如可用与字符窜长度key = len排序,忽略大小写排序key = str.lower比较等功能
  • 可用于list.sort(), sorted(), min(), max()等函数
  • 另外一些其他标准库也会接受这个参数,用法相似

Foreach局部变量

  • Python for循环语句中的“局部”变量与Java中的不同
    1
    2
    3
    # Python
    for i in range(0, 10):
    pass
1
2
// Java
for(int i=1; i < 10; i++)
  • 上面的代码执行完之后i的值为多少?
    • Java中i是局部变量,所以在代码执行完成后变量i是不能访问的
    • Python中i是全局变量,所以i的值为最后一次迭代的值9
    • Java中要实现与Python相同的效果,可以使用全局变量(将i的定义放到for循环外面即可)

函数内部定义函数时注意

  • 注意内部函数是否访问到Inner外的变量
  • 如果某个函数Otter只被访问一次且另一个函数Inner只被Otter访问,那么Inner一般定义在Otter内部比较合适

正则表达式匹配完整字符串

  • 必须使用^和$, 否则部分匹配也会返回结果
    1
    2
    3
    4
    5
    import re
    def totally_match(pattern, string):
    if re.match(pattern, string) is not None:
    return True
    totally_match(r"^cat$", "cat")

函数定义后再定义全局变量

1
2
3
4
def visit():
print global_variable
global_variable = "testing"
print visit()

Python无穷大的数

常用的是无穷大的实数:

  • 正无穷: float(‘inf’)
  • 负无穷: float(‘-inf’)

运算:

  • Python里面的无穷大与C++不同,C++里面是定义一个最大的整数实现,Python里面可以视为一个无穷大的对象

  • 和数学分析里面一样,我们可以和无穷大做计算,加上无穷大还是无穷大

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    x = float('inf')
    print x
    print x - 1
    print x + 1
    print x + x
    print x - x

    # output
    inf
    inf
    inf
    inf
    nan
    • 无穷大减去无穷大为一个未知结果nan
    • 判断一个数是否为nan,nan == nan返回False

复制一个普通列表时不要用copy模块

  • copy.deepcopy支持对可变对象的深度复制,直到解析到不可变对象为止

    1
    2
    3
    import copy
    list1 = [1,3,4,[5,6]]
    list2 = copy.deepcopy(list1)
  • 如果list对象元素都是不可变对象,那么可以有简便实现

    1
    2
    list1 = [1,3,4,5,6]
    list2 = list1[:]
  • 测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import copy
    list1 = [1, 3, 4, [5, 6]]
    l1 = list1[:]
    l2 = copy.deepcopy(list1)
    l3 = copy.copy(list1)
    l4 = list1
    list1.append(10)
    list1[3].append(7)
    print "l[:]", l1
    print "deepcopy", l2
    print "copy", l3
    print "l", l4

    # output
    l[:] [1, 3, 4, [5, 6, 7]]
    deepcopy [1, 3, 4, [5, 6]]
    copy [1, 3, 4, [5, 6, 7]]
    l [1, 3, 4, [5, 6, 7], 10]

not " "返回的是False

  • 在编程时容易错误的以为空白就是没有,所以容易认为not " "是True
    • " "不是什么都没有,而是有个space字符
  • 实际上只有空字符串,空列表和None等是空的,not None, not [], not ''等均为True
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    print not " "
    print not ""
    print not []
    print not None
    print not 0
    print not -1

    # output:
    False
    True
    True
    True
    True
    False

Python中32位最小和最大整形数

1
2
3
4
# max
max_int = 0x7FFFFFFF
# min
min_int = -0x80000000

使用abs(n)求n的绝对值

1
2
3
print abs(-11)
# output
11

使用整除符号//

1
2
3
4
print 3.5 // 2
print 3.5 / 2
print 3 // 2
print 3 / 2
  • //是整除符号,只保留整数部分,但是结果的类型可能为整数,也可能为浮点数,具体取决于除法两边是否含有浮点数

list中的子列表

1
2
3
4
5
6
l = [1,2,3,4,5]
print l[2:-1]
print l[-1]
# output
[3, 4]
5
  • listl中使用-1可以理解为len(l)-1,不管是字列表还是元素的索引操作

sorted的返回值总是list

  • 即使传入的是一个string,返回值也是list,需要牢记
    1
    2
    3
    print sorted("1523")
    # output:
    ['1', '2', '3', '5']

Python的for循环语句结束时i的值与Java不同

  • Python

    1
    2
    3
    4
    5
    6
    for i in range(0, 5):
    print i
    print "final:", i
    # output
    0 1 2 3 4
    final: 4
  • Java/C++

    1
    2
    3
    4
    5
    6
    7
    8
    9
    int i;
    for(i = 0; i < 5; i++){
    System.out.print(i);
    }
    System.out.print("final:")
    System.out.print(i)
    # output
    0 1 2 3 4
    final: 4
  • 如果想得到Java/C++的效果,可以使用while语句

    1
    2
    3
    4
    5
    6
    7
    8
    i = 0
    while i < 5:
    print i
    i+= 1
    print "final:", i
    # output
    0 1 2 3 4
    final: 4

join函数调用的条件

  • 特别注意: join函数的参数只能是字符串,不能是数字

    1
    2
    3
    4
    5
    l = [1,2,3,4]
    print ''.join(l)

    # output
    TypeError: sequence item 0: expected string, int found
    • 使用非string元素的列表时抛出TypeError的错误

dict.get()

  • 原始定义

    1
    dict.get(key[,default=None])
    • default参数可以指定默认值,当key值不存在时可以返回默认值,如果不指定,则默认key值不存在时返回None
  • 与dict[key]对比

    • 使用dict[key]时要确保key在dict中,否则会报异常

一行太长的代码需要分多行

  • 必须在每个子行行尾部使用\

  • 子行内部不用对齐,因为解析时Python解释器会将所有子行合并成一行

  • 示例:

    1
    2
    if 9 < 10 and 11 < 12 and 13 < 14:
    print "works"
    • 等价于

      1
      2
      3
      4
      if 9 < 10 and \
      11 < 12 and \
      13 < 14:
      print "works"
    • 等价于

      1
      2
      3
      4
      if 9 < 10 and \
      11 < 12 and \
      13 < 14:
      print "works"

全局变量只要在函数调用前声明就行了

  • 我们定义函数时,函数里面的变量可以没有定义
  • 调用函数的时候,默认这个函数中没定义过的变量都是全局变量,函数会主动寻找相关的全局变量,找不在再报错
  • 核心: 定义函数时函数中没定义的变量被使用了(如x=10这样的赋值算是变量的定义,不是使用),那么默认函数认为他是全局变量,当函数被调用的时候,才会寻找全局变量是否在当前Python运行环境中
  • 所以,可以先定义函数,再初始化(定义全局变量),最后调用函数
    • 只要初始化全局变量在调用函数之前即可
    • 但是需要注意函数中不能给全局变量赋值,被赋值的变量将被函数认为是局部变量
      1
      2
      3
      4
      5
      6
      7
      8
      def sum_x(y):
      return x+y

      x = 100
      print sum_x(10)

      # output
      110

使用列表切片修改列表

  • 测试代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    a = [1,2,3,4,5,6]
    b = [1,2,3,4,5,6]
    c = [0,0,0,0,0,0]

    a[:2] = c[:2]
    print(a)
    d = b[:2]
    d[:] = c[:2]
    print(d)
    print(b)
    b[:2] = [0]
    print(b)

    # Output:
    [0, 0, 3, 4, 5, 6]
    [0, 0]
    [1, 2, 3, 4, 5, 6]
    [0, 3, 4, 5, 6]
    • 列表切片在左边时,可以修改数组内部数据,甚至是长度都可以修改(最后两行代码)
    • 列表切片在右边时,表现为复制一份列表返回给变量d,所以修改d的值将不影响原始的列表b

使用del删除列表或字典中的元素

  • 删除列表或字典中的元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    l = [1, 2, 3]
    d = {"m": 10, "x": 11}
    print(l)
    print(d)
    del l[0]
    print(l)
    del l[0]
    print(l)
    del d["m"]
    print(d)

    # Output:
    [1, 2, 3]
    {'m': 10, 'x': 11}
    [2, 3]
    [3]
    {'x': 11}
  • 注意不能删除元组中的元素

    1
    2
    3
    4
    5
    6
    7
    8
    t = (1,2,3)
    del t[1]

    # Output:
    Traceback (most recent call last):
    File "/home/jiahong/JupyterWorkspace/test2.py", line 13, in <module>
    del t[1]
    TypeError: 'tuple' object doesn't support item deletion

dict.keys()返回的是列表吗?

代码示例

1
2
3
d = {"m": 10, "x": 11}
print(d.keys())
print(type(d.keys()))

Python 2.7中输出

1
2
['x', 'm']
<type 'list'>

Python 3.6中输出

1
2
dict_keys(['m', 'x'])
<class 'dict_keys'>

总结

  • Python2.7中输出是列表,丢失了set信息,占用空间小,但是会造成使用x in d.keys()时变成线性搜索时间 O(n)
  • Python3.6中输出是dict_keys类型的对象,保留了set信息,占用空间也大了,便于使用x in d.keys()时变成常数搜索时间 O(1)

列表切片的详细说明[::-1]

  • 切片完整用法

    1
    li[start:end:step]
    • start: 开始索引,包含li[start],默认为0
    • end: 结束索引, 不包含li[end],默认为len(li)
    • step: 跳着取元素,step为间隔,默认为1
      • step可以设置为负, 此时若start > end则能得到,从[start,end]结束的序列,包含li[start], 不包含li[end], 由于此时start > end, 所以得到的是逆序列
      • 注意: 若step参数省略的话第二个:也能省略
  • 代码示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    A = [0,1,2,3,4,5,6,7,8,9]
    print(A)
    print(A[::-1])
    print(A[::-2])
    print(A[::1])
    print(A[::2])
    print(A[1:5:])
    print(A[1:5:])
    print(A[5:1:-1])

    # Output:
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    [9, 7, 5, 3, 1]
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    [0, 2, 4, 6, 8]
    [1, 2, 3, 4]
    [1, 2, 3, 4]
    [5, 4, 3, 2]

vars函数的使用

  • 定义

    1
    2
    3
    4
    5
    6
    7
    8
    def vars(p_object=None): # real signature unknown; restored from __doc__
    """
    vars([object]) -> dictionary

    Without arguments, equivalent to locals().
    With an argument, equivalent to object.__dict__.
    """
    return {}
    • vars(object)返回对象的字典
  • 代码示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class A:
    def __init__(self):
    self.a = 10
    self.b = "abc"

    def getA(self):
    self.c = "100"


    a = A()
    print(A.__dict__)
    print(vars(A))

    # Output:
    {'__module__': '__main__', '__init__': <function A.__init__ at 0x7f87b2be01e0>, 'getA': <function A.getA at 0x7f87994c2e18>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
    {'__module__': '__main__', '__init__': <function A.__init__ at 0x7f87b2be01e0>, 'getA': <function A.getA at 0x7f87994c2e18>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
  • 注意: object.__dict__一般在序列化的时候访问,平时不会访问


整数除法(负整数)

  • C++ 和 Java中整数除法是向0取整
  • Python中整数除法是向下取整(向负无穷取整)
  • 正整数除法他们的商和余数都相同
  • 负整数除法商和余数都不同,需要注意,不要用错

如何获取一个正数的小数部分?

  • 方法1

    1
    2
    a = 10.234
    decimal = a - int(a)
  • 方法2

    1
    2
    a = 10.234
    decimal = a % 1

Python——编程规范

Posted on 2018-09-26

Python 编程中经验型的一些规范
持续更新


使用li[:]代替copy.copy(li)

  • li[:]等价于copy.copy(li)
  • li[:]不等价于copy.deepcopy(li)
  • li[:]可以简化代码

从后开始访问列表

  • list作为stack用时访问栈顶元素list[-1]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    list1 = [1, 5, 2, 3]
    print list1[-1]
    print list1[-2]
    print list1[1:-1]

    # output:
    3
    2
    [5, 2]

函数内函数

  • Python可以在函数内部定义函数,但是要注意不能与外部变量混淆
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    def sum_all(alist):

    def sum_two(a, b):
    return a+b

    result = 0
    for i in alist:
    result = sum_two(result, i)
    return result


    print sum_all([1, 2, 3, 4, 5])
    # output:
    15

不要随意调用特殊方法

(比如:__len__)

  • 特殊方法不应该被开发者调用,而应该被开发者定义新类时实现
  • 一般使用len(object)即可
  • 原因: 内置的方法(比如:len())可能会直接返回对象中的ob_size属性,而不用调用__len__()(这个函数往往会用迭代或者其他比较复杂的方法实现)

多使用列表推导

(list comprehension, 简写listcomps)和生成器表达式(generator expression, 简写genexps)

  • listcomps

    1
    [str(i) for i in range(1,10)]
  • genexps

    1
    (str(i) for i in range(1,10))

考虑使用reduce而不是循环语句

  • reduce
    1
    2
    3
    def add(x, y):
    return x + y
    reduce(add, [1,2,3,4,5])
1
2
from operator import mul
reduce(mul, range(1, 10))

多使用pprint

  • (Pretty Print)而不是print
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import pprint
    l1 = (1, {2: 3}, "first", ("second", 5, 6, [7, 8, 9]), [1, 3, 5], "this is a pprint")
    pprint.pprint(l1)

    # Output:
    (1,
    {2: 3},
    'first',
    ('second', 5, 6, [7, 8, 9]),
    [1, 3, 5],
    'this is a pprint')

多使用三目运算符

  • Python不像Java和C++一样,有x?y:z这样的三目运算符号,但是可以有自己的特殊使用方法,等价于三目运算符且更容易理解

    1
    2
    3
    # same as x?y:z
    result = y if x is True else z
    return y if x is True else z
    • 注意: 在使用return语句中的三目运算时必须有else语句,否则编译不通过,因为返回值可能会缺失

匿名变量的使用

  • 初始化一个列表时
    1
    list1 = [_ for _ in list2 if _.val > 10]

Python异常处理

  • 异常处理的正确姿势, 注意如果不是必要的话不要使用Exception, 可以考虑列出来需要捕获的所有异常, 然后在函数内部判断异常类型

    1
    2
    3
    4
    5
    try:
    read some thing
    except IOError, ValueError, e:
    exception_type = type(e)
    print("%s" % e)
  • 当然, 我们一般为了方便也会直接使用下面的方法

    1
    2
    3
    4
    5
    try:
    read some thing
    except Exception, e:
    exception_type = type(e)
    print("%s" % e)

位运算

  • 在Python中, 位运算与C++中有所不同
  • 参见Python——位运算与逻辑运算和C++有什么不同

函数

  • 内部函数访问全局变量时使用global关键字声明(与外部函数一样)
  • 内部函数访问外部函数的变量使用nonlocal(仅限Python 3)关键字声明
  • 如果没有声明
    • 变量变为只读的
      • 可以写出a.append()这样的语句
      • 但不可以写出a = b这样的语句
  • 函数内部变量与函数外同名时:
    • 若写出赋值操作,则认为当前变量为局部变量
    • 否则认为是函数外的全局变量
    • 若先访问变量(一般访问,不是对变量赋值,此时视为全局变量),然后对变量赋值(此时视为局部变量),则产生矛盾,Python解释器报错

三元表达式的使用

  • 如果在三元表达式使用在加法中,需要加上括号,不然整体意思会变成错误的

  • 比如两个结点的加法操作,带有进位carry,我们可以简单的写一行:

    • 下面是错误示例:

      1
      val = l1.val if l1 else 0 + l2.val if l2 else 0 + carry
    • 上面的表达式可以理解为如果l1不为空,返回l1.val,否则返回0 + l2.val if l2 else 0 + carry

    • 当l1为空时又可以理解为如果l2不为空,返回0+l2.val否则返回0+carry

  • 正确的写法

    1
    val = (l1.val if l1 else 0) + (l2.val if l2 else 0) + carry

迭代dict的键时用dict.iterkeys()

  • 迭代键值时使用iterkeys()而不是keys()

  • iterkeys()返回一个迭代器而不是所有键值列表

  • keys()返回所有键值列表

    1
    2
    3
    4
    # 迭代效率高
    for _ in dict.iterkeys()
    # 迭代效率低
    for _ in dict.keys()
  • 迭代值时也同理

    1
    2
    3
    4
    # 迭代效率高
    for _ in dict.itervalues()
    # 迭代效率低
    for _ in dict.values()

zip实现二维列表的行列变换

只适用于Python3,因为涉及到*操作

1
2
3
4
5
6
a = [[1,2,3],
[4,5,6]]

print [e for e in zip(*a)]
# Output
[(1,4), (2,5), (3,6)]
  • Python3中才能使用*作为操作列表解压符
  • Python3中zip函数返回的是一个生成器而不是列表,所以需要迭代成列表

Python中逻辑运算符的巧用

不建议使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
print 0 or 1
print 10 or 1
print None or 1
print 0 and 1
print 1 and 10
print None and 10

# output:
1
10
1
0
10
None
  • 理解

    1
    2
    3
    4
    5
    6
    7
    print a or b 
    <==>
    print a if a else b

    print a and b
    <==>
    print b if a else a
  • 记忆:

    • 把a, b当做逻辑表达式,如果访问到b则返回b,否则返回a

reversed函数的使用

  • 接受参数为可迭代对象,返回一个反向访问迭代对象的迭代器

    1
    2
    3
    4
    5
    for i in reversed(range(n)):

    <==>

    for i in range(n-1, -1, -1):
  • reversed的使用似乎更优雅,也更容易理解

  • 容易遗忘的点,需要注意: reversed的参数必须是可迭代的对象,而不是两个数字


将简单的句子优雅的写到一行

  • 返回值

    1
    2
    3
    4
    if i < 0: return Flase
    <==>
    if i < 0:
    return False
  • 其他简单的执行语句直接合并

    1
    i = 10; j = 10
  • 判断语句之后使用

    1
    if bool: i = 10;
  • 判断语句后使用多条

    1
    if bool: i = 10; j = 20
  • while语句后使用

    1
    while(bool): print 10; print 20
  • 当句子较长时不建议使用

  • 一般为了美观,平时的项目也不建议使用

  • 刷题时为了让代码看起来简便,是可以使用的,但是这样会使得代码不易调试

  • 总之:慎用


用同一个值初始化两个变量

1
x = y = value
  • 在初始化链表头部时最常用
    1
    head, curr = ListNode(None)

使用collections.Counter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import collections

counter = collections.Counter([1, 2, 1, 3, 4, "a", "a", "c"])

print counter
print counter["a"]
print counter[1]
print counter[-1]
print counter.get("a")
print counter.get(-1, 0)

# Output:
Counter({'a': 2, 1: 2, 2: 1, 3: 1, 4: 1, 'c': 1})
2
2
0
2
0

递归函数中定义函数会影响递归函数的运行效率吗?(待更新)

Pandas——apply, applymap和map函数

Posted on 2018-09-26

Pandas库中apply, applymap和map函数的使用


所属类

  • apply: 属于DataFrame类和Series类
  • applymap: 属于DataFrame类
  • map: 属于Series类

作用

  • map 和 applymap都是对每个元素分别操作的:
  • apply
    • 在DataFrame中是对列或者行操作,每一列或者行都是一个Series(列: axis=0[默认值],行: axis=1)
    • 在Series中是对每个元素进行操作(其实换个角度理解为对Series的每一列操作也行,此时的每一列就是一个元素,值得注意的是此时的每个元素是数值类型而不是Series类型,所以不能对其调用sum等函数)

使用方法

# a simple example for apply(), applymap() and map()
func_series = lambda x: x.sum()
func_element = lambda x: "%.2f" % x

df.apply(func_series)
df.applymap(func_element)

ser.apply(func_element)
ser.map(func_element)

PDF——无法打印等权限问题.md

Posted on 2018-09-25

解决PDF的权限问题
很多PDF文件为保护版权,会通过加密来限制打印和修改权限。随着Acrobat DC版本的发布,PDF文件的加密强度已经达到AES 256-bit


在线解密

  • 将文档添加到附件并发送到邮件地址: ocrall@vip.163.com

离线解密

  • 使用一些离线工具,比如eo pdf decrypter等

概率——共轭分布

Posted on 2018-09-25

待更新,共轭分布
参考:LDA数学八卦


扩展——关于共轭分布

  • 高斯分布和高斯分布
    • Gaussion-Gaussion共轭
  • Beta分布和二项分布
    • Beta-Binomial共轭
  • Dirichlet分布和多项分布
    • Dirichlet-Multinomial共轭
1…789…20
Joe Zhou

Joe Zhou

世界上只有一种真正的英雄主义,那就是在认清生活真相之后依然热爱生活。 ——罗曼·罗兰

195 posts
38 tags
GitHub E-Mail
© 2024 Joe Zhou
Powered by Hexo
|
Theme — NexT.Gemini v5.1.4