PyCharm的使用可以参看PyCharm的帮助文档

跳转

  • Command + B(或Command + 单击) 跳转到声明处
  • Command + [ 光标之前的位置
  • Command + ] 光标之后的位置

编辑查找

  • Command + F 当前文件搜索(回车下一个 shift回车上一个)
  • Command + R 当前文件替换
  • Shift + Command + F 全局搜索
  • Shift + Command + R 全局替换
  • Command + O 查找类
  • Shift + Command + O 查找文件
  • Option + Enter 导入包
  • Control + Option + O 整理包导入
  • Option + F7 查找类使用情况

执行

  • Control + Option + R 执行脚本
  • Command + Option + R Debug启动脚本

联系作者

Python中内置的一些属性相关的函数,如dir, getattr, hasattr, setattr, vars, 这里主要来看看一些特殊方法

编写测试代码如下:

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
class Class:
def __delattr__(self, name):
print('## delattr')
super().__delattr__(name)

def __getattr__(self, name):
print('## getattr')
return 'default'

def __getattribute__(self, name):
print('## getattribute')
super().__getattribute__(name)

def __setattr__(self, name, value):
print('## setattr')
super().__setattr__(name, value)


if __name__ == "__main__":
c = Class()
getattr(c, 'name')
print("-----")
c.name
print("-----")
c.data = 'test'
print("-----")
c.data
print("-----")
del c.data

得到输出结果

1
2
3
4
5
6
7
8
9
10
11
## getattribute
## getattr
-----

## getattribute
## getattr
-----

## setattr
-----

## getattribute
-----

## delattr

可以看到c.name和getattr(c, ‘name’)都会调用__getattribute__方法,之后调用__getattr__方法,c.data = ‘test’会调用__setattr__方法,之后c.data只调用了__getattribute__方法, del c.data调用了__delattr__方法。

所以可以总结如下

  • __getattribute__在获取属性时都会被调用到
  • __getattr__当对象没有相应的属性时,会被调用
  • __setattr__在设置属性时会被调用
  • __delattr__在删除属性时会被调用

联系作者

在Python中property是一个常用的装饰器,一个常用的用途是将方法变成属性访问。另一个需要注意的是,使用它可以改变对象中属性的访问顺序。

编写如下测试类

1
2
3
4
5
6
class Class:
data = 'the class data attr'

@property
def prop(self):
return 'the prop value'

然后在交互环境下测试如下

1
2
3
4
5
6
7
8
9
10
11
12
>>> obj = Class()
>>> vars(obj) #
{}
>>> obj.data #
'the class data attr'
>>> obj.data = 'bar' #
>>> vars(obj) #
{'data': 'bar'}
>>> obj.data #
'bar'
>>> Class.data #
'the class data attr'

可以看到在obj.data = ‘bar’后,对象中的data覆盖了类中的data

当对于proptery,对象中的attribute无法覆盖类中的attribute,在交互条件下输入如下操作可以看到结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> Class.prop #
<property object at 0x1072b7408>
>>> obj.prop #
'the prop value'
>>> obj.prop = 'foo' #
Traceback (most recent call last):
...
AttributeError: can't set attribute
>>> obj.__dict__['prop'] = 'foo' #
>>> vars(obj) #
{'prop': 'foo', 'data': 'bar'}
>>> obj.prop #
'the prop value'
>>> Class.prop = 'baz' #
>>> obj.prop #
'foo'

在对象中,obj.prop = ‘foo’这个操作会报错,这是因为property会覆盖对象的属性,而此时prop还未实现set方法。即便是通过obj.dict设置了prop属性,obj.prop获取到的依然是类中的prop

也就是property会覆盖对象的属性,看下面的例子就很清楚了

1
2
3
4
5
6
7
8
9
10
>>> obj.data #
'bar'
>>> Class.data #
'the class data attr'
>>> Class.data = property(lambda self: 'the "data" prop value') #
>>> obj.data #
'the "data" prop value'
>>> del Class.data #
>>> obj.data #
'bar'

在类属性data变成了property后,即Class.data = property(lambda self: 'the "data" prop value') #, 对象中的data的读取也跟着改变了。

简单来说,就是对象中的属性会覆盖类中的属性,而类中的property会覆盖对象中的属性。同样的,类中的descriptor也会覆盖对象中的属性。

参考资料

联系作者

使用jQuery操作时,发现jQuery常用问答, 都是一些很使用的功能。

如何设置或取消一个checkbox或者radio按钮

这里主要用到prop方法

1
2
3
4
5
6
7
8
// 设置 #x
$( "#x" ).prop( "checked", true );

// 取消 #x
$( "#x" ).prop( "checked", false );

// 获取是否选择 #x
$('#x').prop("checked")

如何从select框中获取所选项的值和文本

1
2
3
4
5
6
7
<select id="myselect">
<option value="1">Mr</option>
<option value="2">Mrs</option>
<option value="3">Ms</option>
<option value="4">Dr</option>
<option value="5">Prof</option>
</select>

这里主要是val和text方法

1
2
3
4
5
// 获取值
$( "#myselect" ).val();

// 获取文本
$( "#myselect option:selected" ).text();

联系作者

select2组件用来替代select, 它的一个最常用功能是搜索功能。

编写如下简单测试代码,可以看看搜索功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<html>
<head>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
</head>
<body>

<select class="js-example-basic-single">
<option value="AL">Alabama</option>
<option value="WY">Wyoming</option>
</select>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>

<script type="text/javascript">
$(document).ready(function() {
$(".js-example-basic-single").select2();
});
</script>

</body>

使用过程中遇到的一个问题是,当改变了select2的值时,改变后的结果没有显示在页面上。在select2 FAQ里有说到这个问题,需要触发change事件。如果只想把change事件限定在select2内,可以使用$('select').trigger('change.select2');

联系作者

用classmethod装饰器修饰的函数,第一个参数是类,classmethod的最常见用途是类构造方法

staticmethod实际上并没什么用,使用函数就可以完成相应的功能。

编写如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
class Demo(object):
@classmethod
def klassmeth(*args):
return args # ... @staticmethod

def statmeth(*args):
return args #

if __name__ == "__main__":
print(Demo.klassmeth())
print(Demo.klassmeth('spam'))
print(Demo.statmeth())
print(Demo.statmeth('spam'))

输出结果如下

1
2
3
4
(<class '__main__.Demo'>,)
(<class '__main__.Demo'>, 'spam')
()
('spam',)

联系作者

在项目中,有一个需求是分配IP,在分配之前,需要判断IP是否已经被使用,也就是判断是否能PING通。

因为使用的开发语音是Python,于是想到使用Python的ping库,但发现需要root权限。之后又想到通过subprocess调用ping命令,能满足需求,但是因为一次需要分配多个IP,于是需要并发执行,这样就需要使用多进程或者多线程,于是暂时先放着。

后来同事说可以使用fping, 因为它支持多个IP地址同时ping, 然后返回可以ping通的IP地址,正好满足这个需求。

查了fping的帮助, 加上-a和-A参数,一个简单的例子如
fping -aA 115.239.210.27 115.236.139.174

现在想来,很多时候工程实践能减少代码的编写就减少,这个场景使用fping这种工具,就是将需要编写的并发代码交给了工具完成。

联系作者

看blinker源码时,看到weakref,也就是弱引用模块,以前看《Fluent Python》时也有看到过,只是没有再实际场景中用过。看介绍,主要是用在缓存时对象释放,以及循环引用等场景。PEP-205有结束这个模块的由来。

下面是一个缓存使用中的例子,先声明一个Cheese类

1
2
3
4
5
6
7
class Cheese(object):

def __init__(self, kind):
self.kind = kind

def __repr__(self):
return 'Cheese(%r)' % self.kind

之后在交互环境中执行如下操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> import weakref
>>> stock = weakref.WeakValueDictionary()
>>> catalog = [Cheese('Red Leicester'), Cheese('Tilsit'), Cheese('Brie'), Cheese('Parmesan')]
>>> for cheese in catalog:
... stock[cheese.kind] = cheese
...
>>> sorted(stock.keys())
['Brie', 'Parmesan', 'Red Leicester', 'Tilsit']
>>> del catalog
>>> sorted(stock.keys())
['Parmesan']
>>> del cheese
>>> sorted(stock.keys())
[]

可以看到当删除catelog对象时,在stock中的对象会自动释放。

对于循环引用的例子,可以参考Python 弱引用的使用

联系作者

在Blinker的源码里看到一个defaultdict实现,记录下来

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
class defaultdict(dict):

def __init__(self, default_factory=None, *a, **kw):
if (default_factory is not None and
not hasattr(default_factory, '__call__')):
raise TypeError('first argument must be callable')
dict.__init__(self, *a, **kw)
self.default_factory = default_factory

def __getitem__(self, key):
try:
return dict.__getitem__(self, key)
except KeyError:
return self.__missing__(key)

def __missing__(self, key):
if self.default_factory is None:
raise KeyError(key)
self[key] = value = self.default_factory()
return value

def __reduce__(self):
if self.default_factory is None:
args = tuple()
else:
args = self.default_factory,
return type(self), args, None, None, self.items()

def copy(self):
return self.__copy__()

def __copy__(self):
return type(self)(self.default_factory, self)

def __deepcopy__(self, memo):
import copy
return type(self)(self.default_factory,
copy.deepcopy(self.items()))

def __repr__(self):
return 'defaultdict(%s, %s)' % (self.default_factory,
dict.__repr__(self))

联系作者