bpython使用技巧_Python 一些小技巧和注意事项

快速反转:a = [1,2,3,4] b = 'abcdefg'

a[::-1] ===> [4,3,2,1], b[::-1]===> 'gfedcba'

正常的代码: list(reverse(a)), list(reversed(b))

使用with语句打开一个文件,可以避免文件读取失败时,文件未关闭的情况

with open(path, 'r') as f:

do_sth_with(f)

格式化输出的时候可以使用空格占位符

>>> dict = {'name': 'sdfsdf', 'age': 'ddd', 'sex': 'man'}

>>> print(f"{dict['name']:10}-----dfk")

>>> prrint("{0:10}----{1:8}" % (dict['name'], dict['age']))

>>> sdfsdf -----dfk

在for 或是 while 循环中使用else的时候需要注意他的使用情况,

在循环中使用了 break的,那么else不会被执行。

如果循环的数据时空的,回立刻执行else语句

如果初始循环的while语句是false,那么else也会立马执行

了解如何在闭包里面使用外围作用域的变量

可以使用关键字 nonlocal来进行注明:

def sort_priority(nums, group):

found = False

def helper(x):

nonlocal found

if x in group:

found = True

return (0, x)

return (1, x)

nums.sort(key=helper)

>>> 运行结果如果不添加nonlocal,found返回的结果是 False,因为他是闭包里面的变量(不可变的变量)相当于是在闭包里面新建来一个变量

Python2 没有nonlocal关键字,但是可以使用list数据类型类实现该功能

def sort_priority(nums, group):

found = [False]

def helper(x):

if x in group:

found[0] = True

return (0, x)

return (1, x)

因为这里的found是一个可变对象(列表)满足符合条件

设置方法默认值的时候,一定要使用None来设置,因为默认值只会在方法被加载的第一次里面调用,生成,后面调用方法的时候,其实是使用之前已经生成的默认值。这样回会出现很奇怪的问题的。

def decode(data, default={}):

try:

return json.loads(data)

except ValueError:

return default

boo = decode("boo")

boo['boo'] = 'boo'

far = decode('far')

far['far'] = far

print(boo) ==> {"boo": "boo", "far": "far"}

print(far) ==> {"boo": "boo", "far": "far"}

两次输出的结果是一样的,这是因为在方法加载的时候,返回的是同一个默认值。

尽量使用辅助类来维护程序的状态,而不是使用字典或是元组

使用函数充当API挂钩,在方法参数中,应该传递一个方法,而不是类的实例。

可以定义新的类来记录函数的状态,并且新的类需要实现call方法。

总是使用内置的 super函数 来初始化父类。

使用mix-in 组建实现的效果,就不要使用多继承去实现。

多使用public 少用 private

Python 会对私有属性的名称做一些简单的变换,以保证private的字段的私密性,私有属性字段的真实姓称是: _ClassName__privateName

def MyParentObject(object):

def __init__(self):

self.__private_field = 7

def MyChildrenObject(MyParentObject):

def get_private_field(self):

return self.__private_filed

baz = MyChildrenObject()

baz.get_private_field()

===>> 这里是回报错的,因为在子类里面不能直接访问父类的私有实例变量,因为上面说的,私有变量实际名称是会被更改的,因此在子类里面调用父类的私有变量其实是不存在的。

如果了解私有变量的变量名变更规则,那么在任何地方都可以调用私有变量了。

print(baz._MyParentObject__private_field)

====> 7

camelCase 转换成 snake_case

def camel_to_snake(name):

"""

A function that converts camelCase to snake_case.

Referred from: https://stackoverflow.com/questions/1175208/elegant-python-function-to-convert-camelcase-to-snake-case

"""

import re

s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)

return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()

class SnakeCaseMetaclass(type):

def __new__(snakecase_metaclass, future_class_name,

future_class_parents, future_class_attr):

snakecase_attrs = {}

for name, val in future_class_attr.items():

snakecase_attrs[camel_to_snake(name)] = val

return type(future_class_name, future_class_parents,

snakecase_attrs)

您可能想知道我们在这里为什么使用 __new__ 而不是 __init__。__new__ 实际上是创建实例的第一步。它负责返回类的新实例。而在另一方面,__init__ 则不会返回任何内容。它只负责在创建实例后对其进行初始化。请牢记一条简单的经验法则:当需要控制新实例的创建时使用 new,而在需要控制新实例的初始化时则使用 init。

当列表不是首选时

如果需要存入大量的数据时,可以使用数组(比如要存放1000万个浮点数,数组的效率会高很多,因为数组 里面并不是存放float对象,而是数字的机器翻译,就是字节表述)

如果需要对列表进行先进先出的操作, deque(双端队列)的速度应该会更快。

使用dis.dis反汇编函数,可以查看方法的字节码运行情况。

从python3.3之后,python解释器会在创建str的时候自动计算为str分配最经济的内存,如果字符都在latin1字符集中�那就使用一个字节存储每个码位,否则根据字符串中的每个字符,分配 2 或 4 个字节存储每个码位。

详细链接

判断对象能否被调用,最好使用内置的方法 callable()进行判断。

[callable(obj) for obj in (len, str, 23)]

===>> [True, True, False]

python里面 == 比较的是值相等,但是 is not 或是 is 比较的是对象引用空间分配的内存地址是否相等。或是可以使用 id() 这个方法判断两个变量指向的对象是否是同一个。

>>> a = {"name": 'MrXi', "age": 27}

>>> b = {"name": 'MrXi', "age": 27}

>>> a == b

>>> True

>>> a is not b

>>> True

>>> id(a)

>>> id(b)

方法 del不会删除对象,但是会删除对象的引用,从而导致对象无法被获取,产生对象被删除的现象。(其实对象在长时间未被使用的情况下,会被垃圾回收机制处理。也会被删除)

变量保存的是引用,因此如下的规则需要谨记

简单的赋值不创建副本

对 += 或是 *= 所做的增量赋值来说,如果左边的变量绑定的是不可变对象,会创建新对象;如果是可变对象,会就地修改。

为现有的变量赋予新值,不会修改之前绑定的变量。这叫重新绑定:现在变量绑定了其他对象。如果变量是之前那个对象的最后一个引用,对象会被当作垃圾回收。

函数的参数以别名的形式传递,这意味着,函数肯能会修改通过参数传入的可变对象,这一行为无法避免,除非在本地创建副本,或者使用不可变对象。

使用可变类型作为函数参数的默认值有危险,因为如果就地修改了参数,默认值也就变了,这会影响以后使用默认值的调用。

你可能感兴趣的:(bpython使用技巧)