『天池训练营』python基础入门

本文是在天池学习路线中的『python基础入门』板块, 之前学习过部分, 在此记录一些易错点和不熟悉的地方. 仅作补充, 并不是全部知识点.

详细知识点的所有代码均可在我的GitHub仓库TianChi-Studying中找到.

本笔记为阿里云天池龙珠计划Python训练营的学习内容,链接为:https://tianchi.aliyun.com/specials/promotion/aicamppython;

运算符

位运算

位运算对于我们人类来说是反直觉的, 而对于计算机来说是更加符合计算方式的, 所以位运算的速度通常来的较快.

二进制有原码-反码-补码3种形式, 计算机存储的二进制是补码的形式.

正数的原码补码和反码都相同.

负数是开头使用一位符号位1, 其余部分: 原码同正数, 反码取反, 补码是反码+1.

例如:

# 原码
0000 0011 -> 3
1000 0011 -> -3
# 反码
0000 0011 -> 3
11 11 1100 -> -3
# 补码
0000 0011 -> 3
1111 1101 -> -3

那我们来看看python中二进制转换函数bin的表现吧.

print(bin(3))  # 0b11
print(bin(-3))  # -0b11

print(bin(-3 & 0xffffffff))  
# 0b11111111111111111111111111111101

⚠️ 注意到-3 是不是跟我们说的不一样(@_@😉, 而实现正则的负数需要和0xffffffff按位与才行, 记住就行.

下面列举常见操作符:

操作符名称示例
~按位取反~4
&按位与4 & 5
|按位或4 | 5
^按位异或4 ^ 5
<<左移4 << 2
>>右移4 >> 2

一般多用于快速计算2的倍数.

n << 1  # 计算 n*2
n >> 1  # 计算 n/2,负奇数的运算不可用
n << m  # 计算 n*(2^m),即乘以 2 的 m 次方
n >> m  # 计算 n/(2^m),即除以 2 的 m 次方
1 << n  # 2^n

在算法中也经常有使用整数的二进制位来表示类似数组元素存在与否, 可以降低时空复杂度, 不在此处阐述. 当然还有其他的技巧, 可以多搜搜看.

补充2个位运算的小技巧: 练习的话可以参考leetcode231. 2 的幂191. 位1的个数

  • 判断偶数: (n & 1)
  • 消去二进制位最后一个1: (n & (n-1))

is 和 ==

  • is: 表示是或不是;
  • ==: 表示等或不等.

看起来差别不大, 但是他们比较的对象不同

  • is: 比较的是变量的内存地址;
  • ==: 比较的是变量的.

针对不可修改的变量, 例如字符串, 值相同的变量, 指向的内存地址是一致的.

a = "hello"
b = "hello"
print(a is b, a == b)  # 结果是 True True
print(a is not b, a != b)  # 结果是 False False

针对可修改的变量, 例如列表, 每次创建新变量都是会重新开辟内存地址的.

a = ["hello"]
b = ["hello"]
print(a is b, a == b)  # 结果是 False True
print(a is not b, a != b)  # 结果是 True False

运算符优先级

运算符描述
**指数(最高优先级)
~ + -按位翻转, 一元加号和减号
* / % //乘, 除, 取模和取整
+ -加法减法
>> <<右移, 左移运算符
&按位与
^ |按位取反, 按位或
<= < > >=比较运算符
<> == !=等于运算符
= %= /= //= -= += *= **=赋值运算符
is 和 is not身份运算符
in 和 not in成员运算符
not and or逻辑运算符

数据类型

浮点型

浮点型的赋值还可以使用e来表示

a = 0.00000023
b = 2.3e-7
print(a)  # 2.3e-07
print(b)  # 2.3e-07

如果精度要求比较高可以考虑使用decimal库, 一般感觉很少需要.

import decimal
from decimal import Decimal

判断数据类型

使用isinstance查看数据类型是否符合预期.

print(isinstance(1, int))  # True
print(isinstance(5.2, float))  # True
print(isinstance(True, bool))  # True
print(isinstance('5.2', str))  # True

循环

与else

之前知道while循环后可以跟一个else, 但是感觉没什么用, 最近刷leetcode后再学习这个知识, 发现原来是whilebreak的话else可以不执行, 感觉稍微有些用了, for也同理可跟else.

for num in range(10, 20):  # 迭代 10 到 20 之间的数字
    for i in range(2, num):  # 根据因子迭代
        if num % i == 0:  # 确定第一个因子
            j = num / i  # 计算第二个因子
            print('%d 等于 %d * %d' % (num, i, j))
            break  # 跳出当前循环
    else:  # 循环的 else 部分
        print(num, '是一个质数')

# 输出
# 10 等于 2 * 5
# 11 是一个质数
# 12 等于 2 * 6
# 13 是一个质数
# 14 等于 2 * 7
# 15 等于 3 * 5
# 16 等于 2 * 8
# 17 是一个质数
# 18 等于 2 * 9
# 19 是一个质数

与enumerate

enumerate(sequence, [start=0])
  • sequence:一个序列、迭代器或其他支持迭代对象.
  • start:下标起始位置.
  • 返回 enumerate(枚举) 对象.

enumerate(A) 不仅返回了 A 中的元素, 还顺便给该元素一个索引值 (默认从 0 开始). 此外, 用 enumerate(A, j) 还可以确定索引起始值为 j.

languages = ['Python', 'R', 'Matlab', 'C++']

for i, language in enumerate(languages, 2):
    print(i, 'I love', language)
print('Done!')
# 2 I love Python
# 3 I love R
# 4 I love Matlab
# 5 I love C++
# Done!

元组推导式和next

列表推导式得到的结果是一个列表无疑. 而元组推导式得到的结果是一个『生成器对象』, 这一点需要注意一下. 如果需要转化成元组, 则使用tuple()函数.

此外, 需要使用生成器对象时, 可以使用next(iterator[, default])进行遍历.

e = (i for i in range(10))
print(e)
# <generator object <genexpr> at 0x0000007A0B8D01B0>

print(next(e))  # 0
print(next(e))  # 1

for each in e:
    print(each, end=' ')
# 2 3 4 5 6 7 8 9
print()

# print(next(e))  # StopIteration
print(next(e, 'hh'))  # hh

可以发现, 不管是使用next还是for循环进行遍历, 生成器对象的元素每输出一次都会减少一个, 是一次性消耗品.

对next函数给定默认值时, 则会在生成器对象为空时输出默认值, 否则抛出StopIteration异常.

异常处理

标准异常

1. Python 标准异常总结

  • BaseException:所有异常的 基类
  • Exception:常规异常的 基类
  • StandardError:所有的内建标准异常的基类
  • ArithmeticError:所有数值计算异常的基类
  • FloatingPointError:浮点计算异常
  • OverflowError:数值运算超出最大限制
  • ZeroDivisionError:除数为零
  • AssertionError:断言语句(assert)失败
  • AttributeError:尝试访问未知的对象属性
  • EOFError:没有内建输入,到达EOF标记
  • EnvironmentError:操作系统异常的基类
  • IOError:输入/输出操作失败
  • OSError:操作系统产生的异常(例如打开一个不存在的文件)
  • WindowsError:系统调用失败
  • ImportError:导入模块失败的时候
  • KeyboardInterrupt:用户中断执行
  • LookupError:无效数据查询的基类
  • IndexError:索引超出序列的范围
  • KeyError:字典中查找一个不存在的关键字
  • MemoryError:内存溢出(可通过删除对象释放内存)
  • NameError:尝试访问一个不存在的变量
  • UnboundLocalError:访问未初始化的本地变量
  • ReferenceError:弱引用试图访问已经垃圾回收了的对象
  • RuntimeError:一般的运行时异常
  • NotImplementedError:尚未实现的方法
  • SyntaxError:语法错误导致的异常
  • IndentationError:缩进错误导致的异常
  • TabError:Tab和空格混用
  • SystemError:一般的解释器系统异常
  • TypeError:不同类型间的无效操作
  • ValueError:传入无效的参数
  • UnicodeError:Unicode相关的异常
  • UnicodeDecodeError:Unicode解码时的异常
  • UnicodeEncodeError:Unicode编码错误导致的异常
  • UnicodeTranslateError:Unicode转换错误导致的异常

断言 assert 关键词

assert这个关键词我们称之为『断言』, 当这个关键词后边的条件为 False 时, 程序自动崩溃并抛出AssertionError的异常.

age = 17;
assert age > 18 # 程序停止, 抛出异常

常用于单元测试.

try - except - finally 语句

之前我也一直以为finally没什么用的, 这次学到了.

  • try没有异常, 那么程序执行完try后执行finally;
  • try存在异常, 并被except拦截到了, 那么执行except后执行finally;
  • try存在异常, 但是没有被except拦截到, 那么执行finally, 报错!
def divide(x, y):
    try:
        result = x / y
        print("result is", result)
    except ZeroDivisionError:
        print("division by zero!")
    finally:
        print("executing finally clause")


divide(2, 1)
# result is 2.0
# executing finally clause

divide(2, 0)
# division by zero!
# executing finally clause

divide("2", "1")
# executing finally clause
# TypeError: unsupported operand type(s) for /: 'str' and 'str'

raise语句

Python 使用raise语句抛出一个指定的异常.

try:
    raise NameError('HiThere')
except NameError:
    print('An exception flew by!')
    
# An exception flew by!

之前我一直以为raise没什么用, 这次还是o()q.

参考

  1. 内容来自python训练营
  2. Python 元组推导式

个人收获

巩固了python基础知识, 补充了一些小知识, 一鼓作气继续学.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值