Jiahong 的个人博客

凡事预则立,不预则废


  • Home

  • Tags

  • Archives

  • Navigation

  • Search

Numpy——reshape函数


维度确定

规则为从前到后,参数由外到内,由行到列

  • values.reshape(2,3) 表示二行三列(2,3)
  • values.reshape(4,2,3) 表示四个(2,3),四个两行三列
  • values.reshape(5,4,2,3) 表示五个(4,2,3)

reshape本质理解

实际上numpy多维数组变化维度时,内存数据没有变化,只是有一个shape参数指明维度即可

  • 每次变化维度的过程可以理解为先将维度还原到(参考:维度确定)一维数组,然后再转化成制定的目标维度
  • 返回的是新对象,但是新老对象数据共享,只有shape等内部属性不一样,所以reshape操作不浪费内存,也不耗费时间,但是需要注意数据共享可能造成的误操作
    • 测试说明: 使用DataFrame.values.reshape()生成的新对象内存数据不共享

特殊参数 “-1“

用于智能补齐某一维度,只能有一个参数为-1

  • 除了-1参数外,其余的部分一定要能够被整除
  • -1本身占用一个维度
  • 假设一维数组维度为12
    • (-1, 2) <==> (6, 2) <==> (6, -1)
    • (-1) <==> (12)

Numpy——transpose函数

用于矩阵维度的转换


transpose函数的使用

  • 用法说明

    1
    nums.transpose(dims)
    • nums为np.ndarray类型的对象
    • dims为表示维度排列的tuple
      • 对于二维矩阵,只有0, 1两个维度,所以只能是(0,1), (1,0)
      • 三维矩阵,有0,1,2三个维度,所以可以是是(0,1,2)的所有全排列,共6个

简单易懂的解释

  • 只改变维度, 每一维度对应的数据不会变, 比如图片的shape为: (28, 28, 3),那么无论怎么变化维度, 变换后的数据中维度大小为3的那个维度都是表示通道, (28,28)总是表示图片的每个通道的数据
  • 原始numpy.ndarray,shape为(2,3,4)
    • .transpose((0,1,2)): shape为(2,3,4), 不变
    • .transpose((1,0,2)): shape为(3,2,4)
    • .transpose((2,1,0)): shape为(4,3,2)
  • 测试代码
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    import numpy as np

    origin = np.random.random_integers(1, 100, (2,3,4))
    print("-"*20 + "origin")
    print(origin)
    print("-"*20 + "(0,1,2)")
    print(origin.transpose((0,1,2)))
    print("-"*20 + "(1,0,2)")
    print(origin.transpose((1,0,2)))
    print("-"*20 + "(2,1,0)")
    print(origin.transpose((2,1,0)))

    # Output:
    --------------------origin
    [[[50 36 80 53]
    [45 45 94 91]
    [49 29 69 53]]

    [[85 83 61 18]
    [16 89 80 60]
    [99 13 36 40]]]
    --------------------(0,1,2)
    [[[50 36 80 53]
    [45 45 94 91]
    [49 29 69 53]]

    [[85 83 61 18]
    [16 89 80 60]
    [99 13 36 40]]]
    --------------------(1,0,2)
    [[[50 36 80 53]
    [85 83 61 18]]

    [[45 45 94 91]
    [16 89 80 60]]

    [[49 29 69 53]
    [99 13 36 40]]]
    --------------------(2,1,0)
    [[[50 85]
    [45 16]
    [49 99]]

    [[36 83]
    [45 89]
    [29 13]]

    [[80 61]
    [94 80]
    [69 36]]

    [[53 18]
    [91 60]
    [53 40]]]

与reshape的区别

reshape的用法:
1
nums.reshape(shape)
* `nums`为`np.ndarray`类型的对象
* `shape`为表示维度排列的`tuple`
    * `shape`必须与原始`nums.shape`兼容,即每个`shape`元素相乘的结果相等
  • 从numpy中矩阵的存储开始讲起,numpy存储数据是C++的方式存储为一行的,然后分为不同shape以不同方式进行索引
  • reshape相当于是把原始数据先还原成一行(实际上没操作),然后再转变成指定shape的数据,本质上数据存储没变化,只是shape变了,以后索引方式也就变了
区别
  • reshape修改的只是shape,每个维度的意义变了
  • transpose修改的只是维度,同时shape跟着变化而已,每个维度的顺序变了,但是意义不会变

Sklearn——CountVectorizer使用介绍


导入

1
from sklearn.feature_extraction.text import CountVectorizer

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 新建一个CountVectorizer对象,以下简称CV对象
vectoerizer = CountVectorizer(min_df=min_df, max_df=max_df, stop_words=stop_words, token_pattern=r"(?u)\b[\w-][\w-]+\b")

# 使用文本集合(一个文本的列表)训练当前CountVectorizer对象
# texts = ["this is a text", "this is another text"]
vectoerizer.fit(texts)

# 训练后可以读取当前CV对象信息
bag_of_words = vectoerizer.get_feature_names()

# 使用CV对象生成任意文本集合的信息,返回对象是文档到字典的数组统计(统计单词数量)
# 这里的texts不必要是之前使用过的,可以是新的文本集合,但是词典已经确定,不能再拓展了,不存在字典中的词直接忽略
X = vectoerizer.transform(texts)

# 使用X对象,toarray()将返回 term/token counts 矩阵,可直接用于TfidfTransformer等对象的训练
X.toarray()

重要参数说明

  • min_df: 用于排除出现次数太少的terms

    • min_df = 0.01 意味着将忽略出现在少于%1的文档中的词
    • min_df = 5 意味着将忽略只出现在5篇以下文档中的词,不包括5篇
  • max_df:

    • max_df = 0.50 意味着将忽略出现在多于%50的文档中的词
    • max_df = 25 意味着将忽略出现在25篇以上文档中的词,不包括25篇

Python——并发模型

本文介绍Python中的并发机制,并给出一种最简洁的Python并发库


使用协程(yield语句)

  • 实现随时暂停和开始
  • 完全串行的操作,无法实现时间上的并行,这里指的是不能同时进行某个操作
  • 与Go语言的协程不同,Python的协程更像是一个“生成器”

使用线程

  • 参考threading模块实现自己的线程

使用concurrent.futures

实现线程池模型

  • 实现一般的线程池模型,代码如下,关键代码仅仅两行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import time
    from concurrent import futures

    def sleep_one_second(key):
    time.sleep(1)
    return "[%s]Done" % key

    ml = "ABCDEFGHIJ"
    with futures.ThreadPoolExecutor(10) as executor:
    res = executor.map(sleep_one_second, ml)

    print([r for r in res])
  • 上面的代码可以在一秒内执行完成,因为共有10个线程并发

  • 在实现爬虫程序时,如果需要爬取的某些数据是相对独立的,那么我们完全可以用线程池实现,而不用使用复杂的线程模块*

    实现进程池模型

  • 仅仅需要修改futures.ThreadPoolExecutor为futures.ProcessPoolExecutor即可

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import time
    from concurrent import futures

    def sleep_one_second(key):
    time.sleep(1)
    return "[%s]Done" % key

    ml = "ABCDEFGHIJ"
    with futures.ProcessPoolExecutor(10) as executor:
    res = executor.map(sleep_one_second, ml)

    print([r for r in res])

进程与线程内存区别

对全局变量的访问对比
  • 线程:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    from concurrent import futures
    global_list = []

    def test_futures(range_num):
    global_list.append(range_num)
    print global_list
    return range_num

    with futures.ThreadPoolExecutor(8) as executor:
    res = executor.map(test_futures, range(10))

    print "the final global_list: %s" % global_list
    • 上面的代码输出如下:

      [0]
      [0, [10, 2]
      , 1[0, 1, 2, , 32]
      , 3, [04, 1], 2, 3, 4
      [0, , 5]
      1, [0, 21, 2, [3, , 3, 044, , 51, , 6, , 75]
      2, [0, 1, 63, 7, , 2, 3[40, , 8, , 4, 9, 155, , 6, 2]6, , 7
      , 8, 7, 9, ]3
      8, 4, , 59, 6, ]
      7, 8, 9]
      the final global_list: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
      the results: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

  • 进程:

from concurrent import futures
global_list = []

def test_futures(range_num):
    global_list.append(range_num)
    print global_list
    return range_num

with futures.ProcessPoolExecutor(8) as executor:
    res = executor.map(test_futures, range(10))

print "the final global_list: %s" % global_list
    • 上面的代码输出如下:

      [0]
      [1]
      [2]
      [3]
      [0, 4]
      [5]
      [6]
      [7]
      [1, 8]
      [2, 9]
      the final global_list: []
      the results: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

  • 原因分析

    • 线程之间共享地址空间,所以所有的线程线程访问同一个全局共享变量
    • 进程之间不共享地址空间,所以不同进程访问不同共享变量
    • 在程序中Process之间不共享地址空间,但是futures.ProcessPoolExecutor(max_workers)任务分配时受限与参数max_workers的影响,所以可以预估本地机器最多开启max_workers个进程,同一进程中地址空间共享,所以会有部分任务被分配给同一进程的不同线程,从而出现部分共享变量被不同任务访问到
    • 总结:
      • futures.ThreadPoolExecutor单进程多线程中全局变量共享
      • futures.ProcessPoolExecutor多进程多线程中每个进程内部的线程全局变量共享
      • 不同进程之间即使时全局变量也不能共享

Python中进程 VS 线程

  • Python中由于全局解释器锁(GIL)的存在,同一进程中的所有线程使用同一个解释器对象,所以它们无法真正实现并行
  • 所以在想要充分利用多核的时候,需要选择使用多进程
  • 更多信息参考Process和Thread分析

MySQL——数据库导入导出

参考博客: https://blog.csdn.net/u013626215/article/details/88548342


从MySQL中导出数据库信息

  • 导出所有表结构

    1
    mysqldump -h [host_ip] -u [user_name] -p -d [db_name] > [file_name]
  • 导出所有表结构和数据

    1
    mysqldump -h [host_ip] -u [user_name] -p [db_name] > [file_name]
  • 导出某一张表结构

    1
    mysqldump -h [host_ip] -u [user_name] -p -d [db_name] [table_name] > [file_name]
  • 导出某一张表结构和数据

    1
    mysqldump -h [host_ip] -u [user_name] -p [db_name] [table_name] > [file_name]

导入数据库到MySQL

  • 登录数据库

    1
    mysql -h [host_ip] -u [user_name] -p
  • 执行导入命令

    1
    source [file_name]
  • 注意: 数据导入需要提前创建数据库

Python——抽象类和继承与Java的不同点

Python也开始支持抽象类和多态了,但是Python的继承与Java有很多不同的地方


Python只有私有属性

(双下划线__属性)和公有属性(默认属性),没有protected属性

  • 解决方案是Python提出命名时单下划线的属性为protected属性
    • 但是这只是一种口头约定,Python解释器并不做强制处理
  • 模块中的函数如果是单下划线开头的,那么该函数属于当前模块保护的
    • 此时某些IDE,比如Idea能够给出提示,但是用户仍可访问
    • 编程时建议将模块中不被调用的文件定义为_开头的,这样可以提示自己和别人当前函数不会在模块外被调用

Python类属性定义

属性定义在__init__函数中才能在对象中通过__dict__属性读取到


Python支持虚拟继承

可以欺骗编译器,不用真正实现虚拟基类的所有接口


都是强类型语言

这是他们的相同点,但我觉得写在这里是必要的


方法类型不同

  • Java中有一般方法(实例方法),静态方法(static类名和对象均可直接调用)两种
    • Java中这两种方法也都可以被继承和隐藏 ,而不能被重写(隐藏的意思时换成对应的父类指针还能访问到父类的静态属性和方法)
  • Python中有一般方法(实例方法),静态方法(@staticmethod类名和对象均可直接调用)和类方法@classmethod
    • 对@staticmethod方法的理解是,该方法与类密切相关,但是不需要访问这个类
    • Python的@staticmethod和@classmethod方法调用方式一样,唯一的区别在于@classmethod方法第一个参数必须是当前类(一般命名为cls)
    • Python中的这三种方法都可以被继承和重写

函数定义

  • 三种函数, 普通函数(实例函数), 类函数(classmethod), 静态函数(staticmethod)

普通函数

  • 无需任何装饰器
  • 无论如何定义,函数的第一个参数都会被当成实例对象本身(一般用self)

类函数

  • 装饰器 @classmethod
  • 无论如何定义,函数的第一个参数都会被当成实例对象本身(一般用cls)

静态函数

  • 装饰器 @staticmethod
  • 所有参数都是函数所有,不被占用

Python——ArgumentParser类的使用


整体说明

  • 在 Python 里,argparse.ArgumentParser() 是标准库 argparse 模块的核心部分,其主要功能是解析命令行参数
  • 大部分优秀的开源函数都会使用这个功能

代码示例

  • ArgumentParser类使用示例
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    import argparse

    def main():
    # 创建 ArgumentParser 对象
    parser = argparse.ArgumentParser(
    description='这是一个命令行工具演示程序',
    epilog='示例: python demo.py -n Alice -a 35 --verbose'
    )

    # 添加参数
    # 位置参数 (未添加-为前缀的是位置参数,位置参数是必须给出的)
    parser.add_argument('input_file', help='输入文件路径')

    # 可选参数(添加-或--的是可选参数),同一行可以同时注册-或--,都可以作为输入参数
    # # 但代码内部名字命名规则是--优先-,没有--时,代码内部-才会生效(比如下面的定义下,parser.output 和 parser.x 生效,但是 parser.o 会报错)
    parser.add_argument('-o', '--output', default='output/result.txt', help='输出文件路径') # 调用时使用args.output调用参数
    parser.add_argument('-x', help='x') # 调用时使用args.x调用参数
    parser.add_argument('-n', '--name', default='Guest', help='用户名称') # 调用时使用args.x调用参数
    parser.add_argument('--age', type=int, choices=range(30, 40), help='用户年龄(30-39)')
    # action='store_true'表示这是布尔变量,若传入命令行存在该参数,则该 Python 参数值为 true,否则为 false;'store_false' 则功能相反
    parser.add_argument('--verbose', action='store_true', help='显示详细输出')
    parser.add_argument('--color', choices=['red', 'green', 'blue'], default='blue', help='颜色选择')
    parser.add_argument('--scale', type=float, default=*0, help='缩放比例')

    # 互斥参数组,同时指定会出错
    group = parser.add_mutually_exclusive_group()
    group.add_argument('--fast', action='store_true', help='快速模式')
    group.add_argument('--slow', action='store_true', help='慢速模式')

    # * 解析参数
    args = parser.parse_args()

    print("args对象完整属性:", args.__dict__)
    print("--end--\n")
    # * 使用参数
    print(f"输入文件: {args.input_file}")
    if args.output:
    print(f"输出文件: {args.output}")
    print(f"用户名: {args.name}")
    if args.age:
    print(f"年龄: {args.age}")
    print(f"详细模式: {'是' if args.verbose else '否'}")
    print(f"颜色: {args.color}")
    print(f"缩放比例: {args.scale}")
    if args.fast:
    print("模式: 快速")
    elif args.slow:
    print("模式: 慢速")
    else:
    print("模式: 默认")


    if __name__ == '__main__':
    main()

    # args对象完整属性: {'input_file': 'text.txt', 'output': 'output/result.txt', 'x': None, 'name': 'Guest', 'age': 33, 'verbose': False, 'color': 'blue', 'scale': *0, 'fast': False, 'slow': False}
    # --end--
    #
    # 输入文件: text.txt
    # 输出文件: output/result.txt
    # 用户名: Guest
    # 年龄: 33
    # 详细模式: 否
    # 颜色: blue
    # 缩放比例: *0
    # 模式: 默认

Python 内部变量参数命名规则

  • - 和 -- 同时存在时,优先 -- 定义的变量
    • 注:传入时都可以使用,且没有优先级,只会用后面的覆盖前面的
  • --output-path 等会自动被转换成 parser.output_path 变量访问
    • 注:传入时还是必须跟参数定义方式对齐 --output-path
    • 当然:--output_path 也是相同的参数名 parser.output_path ,若同时定义了 --output_path 和 --output-path,则两者实际上是同一个参数,且互相之间可以被覆盖

ArgumentParser 类其他使用注意事项

  • 参数类型 :
    • 默认情况下参数是字符串类型,可以使用 type 指定其他类型
    • 常用类型:int, float, str (默认)
  • 参数种类 :
    • 位置参数:没有前缀,必须提供
    • 可选参数:以 - 或 -- 开头,可选提供
    • 注:位置参数是必须的,可选参数可通过增加 required=True 来设定为必须参数
  • 常用参数选项 :
    • help:参数的帮助信息
    • default:参数的默认值
    • choices:限制参数的取值范围
    • action:参数的动作,常见值:
      • store:存储参数值(默认)
      • store_true/store_false:存储布尔值
      • append:允许多次使用参数并存储为列表
  • 互斥参数 :
    • 使用 add_mutually_exclusive_group() 创建互斥组
    • 组内的参数不能同时使用
  • 帮助信息 :
    • description:程序的简要描述
    • epilog:帮助信息末尾的文本
    • 自动生成的帮助信息可以通过 -h 或 --help 查看
  • 错误处理 :
    • 当用户输入无效参数时,argparse 会自动生成错误信息并退出,会抛出 ArgumentError 或 SystemExit 异常
  • 子命令 :
    • 对于复杂的命令行工具,可以使用 add_subparsers() 实现子命令功能
    • 类似 git 的 commit, push 等子命令
  • 参数前缀 :
    • 通常单字母参数用 - 前缀,完整单词用 -- 前缀
    • 但这不是强制要求,只是约定俗成

Python——Copy-and-Deepcopy

deepcopy 与 copy 的本质区别——是否为可变对象创建新的对象(内存空间)
以下图片截取自Python Tutorial


代码片段一

  • 可变对象 list 中包含着可变 list 和不可变对象 tuple,且 tuple 中不包含可变对象
    1
    2
    3
    4
    5
    import copy
    l1 = [3, [66, 55, 44], (7, 8, 9)]
    l2 = list(l1) # <==> l2 = copy.copy(l1)
    # <==> l2 = l1[:]
    l3 = copy.deepcopy(l1)

代码片段二

  • 可变对象 list 中包含着可变 list 和不可变对象 tuple, 且tuple中包含可变对象list
    1
    2
    3
    4
    5
    import copy
    l1 = [3, [66, 55, 44], (7, 8, [1, 2])]
    l2 = list(l1) # <==> l2 = copy.copy(l1)
    # <==> l2 = l1[:]
    l3 = copy.deepcopy(l1)

代码片段三

  • 不可变对象中包含可变对象
  • 值得强调的是,copy 复制 tuple时,不会像 list 那样直接创建新对象,无论 tuple 中是否有可变对象
  • 除非包含不可变对象,否则 deepcopy 复制 tuple 时也不会创建新对象
    1
    2
    3
    4
    5
    6
    7
    import copy
    t1 = (3, [66, 55, 44], (7, 8, [1, 2]))
    t2 = t1
    t3 = tuple(t1) # <==> t4 = t1[:]
    # t5 = copy.copy(t1)
    t6 = copy.deepcopy(t1)
    t1[1].append(100)

copy和deepcopy直接对比

  • copy.copy()是浅拷贝,copy.deepcopy()是深拷贝

浅拷贝 (copy.copy())

当你使用 copy.copy() 函数时,它会创建一个新对象,然后将原始对象中包含的所有元素引用都复制到这个新对象中。这意味着如果你修改了原对象中的可变元素(如列表、字典等),那么副本中的这些元素也会受到影响,因为它们实际上是指向同一个内存位置的引用

  • 浅拷贝示例:

    1
    2
    3
    4
    5
    6
    7
    import copy
    original_list = [[1, 2], [3, 4]]
    shallow_copy = copy.copy(original_list)
    original_list[0][0] = 'changed'

    print(original_list) # 输出: [['changed', 2], [3, 4]]
    print(shallow_copy) # 输出: [['changed', 2], [3, 4]]
    • 在这个例子中,对 original_list 的修改也影响到了 shallow_copy,因为子列表是被引用的,而不是被复制的

深拷贝 (copy.deepcopy())

  • copy.deepcopy() 函数则不仅复制了对象本身,还递归地复制了对象中包含的所有对象。因此,新的对象及其包含的所有对象都是完全独立的,对原对象或其内部对象的任何改变都不会影响到深拷贝后的对象

  • 深拷贝示例:

    1
    2
    3
    4
    5
    6
    7
    import copy
    original_list = [[1, 2], [3, 4]]
    deep_copy = copy.deepcopy(original_list)
    original_list[0][0] = 'changed'

    print(original_list) # 输出: [['changed', 2], [3, 4]]
    print(deep_copy) # 输出: [[1, 2], [3, 4]]
    • 在这个例子中,对 original_list 的修改不会影响到 deep_copy,因为所有级别的对象都被复制了

总结

  • 对于不可变对象调用 deepcopy 和 copy 函数时:
    • deepcopy 与 copy 操作一样,都不为创建新对象,而是直接引用
    • 在后面如果有修改该不可变对象的操作时再创建新对象,此时两个版本的不可变对象地址变得不同
    • 这里是 Python 的常态,比如tuple(tuple1)将返回一个 tuple1 对象的引用而不是副本,当修改 tuple1 时才会创建新对象
    • 因为无论如何,修改不可变对象的不可变部分都不会修改原始对象,所以为了节约内存,Python 解释器完全可以将创建新对象延后到修改内容时
  • 对于可变对象调用 deepcopy 和 copy 函数时:
    • 使用 copy.copy() 只复制对象的第一层,对于对象内部的嵌套对象只复制引用
    • 使用 copy.deepcopy() 会递归地复制整个对象结构,包括所有的嵌套对象,从而确保两个对象完全独立。

Python——Python中-m参数的使用


整体说明

  • 在 Python 中,-m 参数是一个非常有用的工具,它允许你将模块作为脚本运行,并且可以处理复杂的包结构。无论是运行标准库模块、自定义模块,还是与包结合使用,-m 参数都能简化操作。它的基本语法如下:

    1
    python -m module_name
  • 其中,module_name 是你要运行的模块名(不包含 .py 后缀)。Python 会在 sys.path 中查找该模块,并执行它


运行标准库模块

  • -m 参数常用于运行 Python 标准库中的模块。例如:

    1
    python -m http.server
  • 这会启动一个简单的 HTTP 服务器,默认监听在 8000 端口。http.server 是 Python 标准库中的一个模块,-m 参数让 Python 将其作为脚本运行


运行自定义模块

  • 你也可以使用 -m 参数运行自定义模块。假设你有一个项目结构如下:

    1
    2
    3
    4
    my_project/
    my_module/
    __init__.py
    main.py
  • 你可以在 my_project 目录下运行以下命令:

    1
    python -m my_module.main

这会执行 my_module/main.py 文件中的代码


运行包中的模块

  • 如果模块位于包中,-m 参数会自动处理包的导入路径。例如:

    1
    python -m package.subpackage.module
  • 这会执行 package/subpackage/module.py 文件中的代码


与 __main__.py 结合使用

  • 如果你有一个包,并且希望在运行包时执行特定的代码,可以在包目录下创建一个 __main__.py 文件。例如:

    1
    2
    3
    4
    my_package/
    __init__.py
    __main__.py
    other_module.py
  • 在 __main__.py 中编写你想要执行的代码,然后运行:

    1
    python -m my_package
    • Python
  • 这会执行 my_package/__main__.py 文件中的代码


与 python -c 结合使用

  • -m 参数也可以与 -c 参数结合使用,直接在命令行中运行模块。例如:

    1
    python -c "import os; print(os.getcwd())" -m http.server
    • 注:python -c "print('hello')"常常用来执行一个Python命令且不需要创建文件

Python——Python中没有Char类型


没有Char类型

不同于C++和Java等语言,Python中没有字符char类型,只有字符串类型


关于字符类型的操作

  • 把长度为1的字符串当成字符来操作,比如函数ord(s)中只要s的长度为1(len(s) == 1)即可,否则ord函数抛出异常
    • 长度为1的字符串本质上还是一个字符串类型<type str>
  • 判断字符串某一位置的字符时直接比较即可,如:
    1
    2
    3
    4
    5
    6
    7
    s = "12345"
    if s[2] == '2':
    print s[3]
    # 等价于
    if s[2] == "2":
    print s[3]
    # "2"和'2'都是<type str>类型的
1…343536…61
Joe Zhou

Joe Zhou

Stay Hungry. Stay Foolish.

608 posts
49 tags
GitHub E-Mail
© 2026 Joe Zhou
Powered by Hexo
|
Theme — NexT.Gemini v5.1.4