Python教程中的思考

一直没能系统性的看看Python,都是用一点学一点,遇到不熟悉的部分效率就很低。
最近终于有时间看看《Python菜鸟教程》和《python编程从入门到实践》,这两部分是很好的入门资料和书籍,感觉新手读完这两就能解决平时80%的问题了。Python也很繁杂,师父领进门,修行靠个人,大体有了把握,遇到实际问题再细致攻克,自认为是效率最高的模式,一口吃个胖子的方法并不可取。

《Python菜鸟教程》:Python3 基础语法 | 菜鸟教程
Python 入门指南 — Python tutorial 3.6.3 documentation
《python编程从入门到实践》:某宝搜索,我愿称为 “python圣经”

1.  python import 导入两个模块同时有同一名称的方法如何调用 ?
python import 导入两个模块同时有同一名称的方法如何调用 ? - myrj - 博客园

2. 不同于C++、Java,python中的变量不需要提前声明,即python是动态语言,变量没有变量类型一说,变量名只是一个引用,引用的对象才有所谓的类型——数据类型。标准的数据类型有6种,可用两个标准衡量(区分):(1)数据类型本身是否为可变数据;(2)数据类型的元素是否是可变数据

数据类型本身是否可变数据类型元素是否接受可变数据类型
Number(数字)否(不可变类型)无元素
String(字符串)否(不可变类型)无元素
Tuple(元组)否(不可变类型)
List(列表)是(可变类型)
Dictionary(字典)是(可变类型)键(key)必须使用不可变类型
值(value)任意数据类型均可

Set(集合)

是(可变类型)

注:Set(集合)不能接受可变数据类型,即集合的元素只能是Number(数字)、String(字符串)、Tuple(元组),但常常需要使集合的元素是另外的集合,因而需要用到 frozenset(s) ,将可变集合类型变为不可变集合类型以此解决。

3. 变量是对象的引用,此处延伸下变量和对象之间的关系,截取自文后笔记(Python3 基本数据类型 | 菜鸟教程):

  • 赋值操作,本质是创建引用
  • 变量是变量,对象是对象,当将某个对象赋值给某个变量时,可以认为是创建了变量对该对象的引用
  • 变量没有数据类型之说,只有对象有,即变量不是直接代表对象或对象占用的内存空间
  • Python中,变量无需提前声明,无需指定其数据类型,其表现完全是动态的,其所为的数据类型决定于当前该变量所引用的对象的数据类型
  • 所谓变量对对象的引用,本质是创建了变量指向对象内存空间的指针
  • 对象内存空间,一般最起码有类型和当前被引用次数这两个信息,类型记录了该对象的数据类型,被引用次数记录了该对象内存空间被变量引用的次数
  • 当某对象的被引用次数为0时,Python便会自动回收该对象内存空间

比如下面的

a=10
a='122'
a=[1,2,3]
del a

此时,a在不同的赋值代码行中,引用的对象类型不同,相当于在不断改变a引用的对象,最后当把a变量删除时,其实本质只是删除了a变量名,但由于a引用的[1,2,3]对象,因为a被删除,其被引用次数变为0,也就自动被Python回收,最终表现就是del a时,[1,2,3]也被删除了。

另外一个小知识是,Python为提升代码执行和内存分配效率,会对一些常用的对象提前创建好,并常驻内存,比如下面:

id(4) #不管运行多少次该代码,其返回的值均不变,因为python会保持一些常用的数字常驻内存,不会每次都重新分配内存空间
id('hello world') #每次运行,返回的值均会发生变化,因为每次运行,相当于都在重新分配内存空间

注:当出现一行多个赋值的时候,如 x = y = ['aaa', 'bbb'] ,其实只是对列表对象创建了多个引用而已,并未实际创建多个对象。所以当改变其中一个引用的某值时,x[0] = 'ccc',那么 y[0] 也会相应改变为 'ccc'

4. 变量(引用)与对象的关系
判断变量是否对应同一个对象,可用 is 判断,var1 is var2; is本质是通过对象的内存id号判断的,即判断变量是否引用同一个对象。
对于python的六种标准数据类型,若数值完全相同,那么只有数字和元组类型的数据id号是相同的。其他类型数据,即使数值完全相同,但具有不同的id。

list1=[1000,3,5]
list2=[1000,3,5]
print(list1 is list2)
tuple1=(1000,3,5)
tuple2=(1000,3,5)
print(tuple1 is tuple2)
str1 = 'aaa'
str2 = 'bbb'
print(str1 is str2)
num1 = 10000
num2 = 10000
print(num1 is num2)
dict1={1:1000,2:3,3:5}
dict2={1:1000,2:3,3:5}
print(dict1 is dict2)
set1 = {'aaa', 'bbb'}
set2 = {'aaa', 'bbb'}
print(set1 is set2)

分别对应列表、元组、字符串、数字、字典、集合类型的数据,判断结果为:
False
True
False
True
False
False

5. 逻辑运算符 and 和 or
and 从左到右计算表达式,若所有值均为真,则返回最后一个真值;若存在假,则返回第一个假值;
or 也是从左到有计算表达式,若有真值,则返回第一个为真的值;若全为假值,则返回最后一个假值。

其中数字 0 是假,其他都是真;字符 "" 是假,其他都是真。

6. python中的进制问题
python中默认输入输出都是十进制

输入进制改变:
 

二进制0b
a = 0b111100
八进制0o
a = 0o77
十六进制0x
a = 0xFF

输出进制改变:
 

二进制bin(a)
八进制oct(a)
十六进制hex(a)

7. max()函数
max(x, y[, z...]):Number|Sequence 入参类型不能混入。要么全Number(int|float|complex|bool),要么全序列,但注意传入的序列类型应保持一致,即要么全传列表,要么全传元组。
入参是序列的话: 单序列入参,返回序列中最大的一个数值多序列入参, 按索引顺序,逐一对比各序列的当前索引位的 “值”,直到遇见最大值立即停止对比,并返回最大值所在的序列(也就是说,多序列入参,返回值依旧是一个序列,而不是数值)

注:如果出现max函数中元素完全相等的情况,那么max函数默认返回第一个对象。

8. round()函数中的坑
Python 中关于 round 函数的小坑 | 菜鸟教程

9. 对象的id问题
python中的对象是关注的焦点,变量名只是变量的一个引用。
变量在内存的存储位置由id标识。
对于不可变数据类型,当其值相同时,其id就相同;对于可变数据类型,其id总是不同的,即使其值相同。
站在python的角度,其实也好理解,如果可变数据类型当值相同,id也相同时,就会出现,两个变量同时引用一个可变内存的情况,那么当其中一个引用改变该类型的某个数据时,那么另一个引用也会被迫改变,这是我们不愿意看到的。但对于不可变类型,其值本身不接受更改,便不存在这个问题。

注:1.python没有自增操作符,可通过a=a+1实现;2.在交互式环境中,编译器会有一个小整数池的概念,会把(-5,256)间的数预先创建好,而当a和b超过这个范围的时候,两个变量就会指向不同的对象了。但在平时的脚本式编程环境(IDE)中,则没有这一说法。

10. 浅拷贝深拷贝问题
根本区别:深拷贝会把可变对象也拷贝一份,而浅拷贝不会。
Python 直接赋值、浅拷贝和深度拷贝解析 | 菜鸟教程
Python 深拷贝和浅拷贝的区别_Rp_的博客-优快云博客_python深拷贝和浅拷贝的区别

11. python基础数据类型转换

其中,转换为string时候,要求元素均为字符类型,否则join会报错。解决:
print(''.join('%s' % item for item in list))
print(''.join('%s' % item for item in tuple))

12. tuple数据类型的元素修改
tuple元组自身是不可变类型数据,不接受元素的修改。因而若想修改元组元素,可先将元组转换为列表,更改完成后,再转换为元组:

tmp = ('aaa', 1, ['aaa', 1])
tmp = list(tmp)
tmp[0] = 9  # 修改元素语句
tmp = tuple(tmp)
print(tmp)

13. 创建dict时,慎用fromkeys()方法
list_ = [1,2,3]
d = dict.fromkeys(list_ , [])
这样创建得到的字典是:
{1:[] , 2:[] , 3:[]}
但这样三个列表的地址是一样的,修改任意一个列表的值会导致所有列表的值都发生改变。
可以用一下方法来解决:
d = {key : [] for key in list_}

14. 多个循环时
当某个循环内仍存在多个循环的时候,要特别注意 for i in ... 中 i 的使用,习惯性的都用 i 表达循环是十分不好的习惯,因为多个循环嵌套时, i 值间会相互覆盖,导致时序错乱,出现难以预料的错误。建议:使用 i, j, m, n 等,并清楚知道每个循环数的作用和意义。

15. 函数中的参数传递问题
若在函数内执行赋值操作,则会生成新的对象,函数中操作的对象就会发生变化。
根据传入参数对象的不同,可分为传不可变对象和可变对象。(注:python 的变量不存在变量类型一说,变量是对对象的引用,只有对象有类型)
传入不可变对象,相当于是C++中的值传递,若在传入后的函数中改变变量值,实际上并不会影响原始参数(传入前的变量对应值),如:
def change(a):
    print(id(a))   # 指向的是同一个对象
    a=10
    print(id(a))   # 一个新对象
 
a=1
print(id(a))
change(a)
主函数中 a 的 id 值,在执行函数前后不变

传入可变对象,相当于是C++中的引用传递,在函数中对对象的改变会影响原始参数

#=======================================================
def changeme( mylist ):
   "修改传入的列表"
   mylist.append([1,2,3,4])
   print ("函数内取值: ", mylist)
   return
 
# 调用changeme函数
mylist = [10,20,30]
changeme( mylist )
print ("函数外取值: ", mylist)
主函数中的 mylist ,在执行函数前后会改变

16. lambda 表达式的合法用例是在不分配函数的情况下使用函数,即只是临时使用函数而不需要重复分配
如:sorted(players, key=lambda player: player.rank)

17. python函数中变量作用域
变量的访问以 L(Local) –> E(Enclosing) –> G(Global) –>B(Built-in) 的规则查找
局部 —> 局部外的局部 (如闭包) —> 全局 —> 内建
一个典型示例程序为:
num = 20  # 全局变量
def outer():
    num = 10  # 局部变量
    def inner():
        global num  # 获取全局变量,注:如果不在函数中修改变量值,只读取时可省略声明
        print (num)
        num = 100  # 修改变量值
        print (num)
    inner()
    print(num)  # 此时会优先输出局部变量值 10
outer()
print (num)  # 输出修改后的全局变量

18. 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值