Function
bind
错误函数用法示例:
'use strict';
var s = ' Hello ';
s.trim();
// 输出'Hello'
var fn = s.trim;
fn();
// Uncaught TypeError: String.prototype.trim called on null or undefined
用fn()
取代s.trim()
, 上述方法的fn()
传入的this
指针是undefined
, 应该这么用:
var s = ' Hello ';
var fn = s.trim;
// 调用call并传入s对象作为this:
fn.call(s)
// 输出Hello
bind()
可以将s
绑定到fn()
的this
上, 修复之前的错误:
var s = ' Hello ';
var fn = _.bind(s.trim, s);
fn();
partial
partial()
创建偏函数;
创建pow2N(n)
实现Math.pow(2,n)
;
'use strict';
var pow2N = _.partial(Math.pow, 2);
pow2N(3); // 8
pow2N(5); // 32
pow2N(10); // 1024
创建cube(x)
,计算x^3
,可以用_
作占位符,固定住第二个参数:
var cube = _.partial(Math.pow, _, 3);
cube(3); // 27
cube(5); // 125
cube(10); // 1000
memoize
用memoize()
自动缓存函数计算的结果:
var factorial = _.memoize(function(n) {
console.log('start calculate ' + n + '!...');
var s = 1, i = n;
while (i > 1) {
s = s * i;
i --;
}
console.log(n + '! = ' + s);
return s;
});
// 第一次调用:
factorial(10); // 3628800
// 注意控制台输出:
// start calculate 10!...
// 10! = 3628800
// 第二次调用:
factorial(10); // 3628800
// 控制台没有输出
但是factorial(9);
仍然会重新计算, 可以利用递归调用实现阶乘的逐步缓存:
var factorial = _.memoize(function(n) {
console.log('start calculate ' + n + '!...');
if (n < 2) {
return 1;
}
return n * factorial(n - 1);
});
factorial(10); // 3628800
// 输出结果说明factorial(1)~factorial(10)都已经缓存了:
// start calculate 10!...
// start calculate 9!...
// start calculate 8!...
// start calculate 7!...
// start calculate 6!...
// start calculate 5!...
// start calculate 4!...
// start calculate 3!...
// start calculate 2!...
// start calculate 1!...
factorial(9); // 362880
// console无输出
once
once()保证某个函数执行且仅执行一次:
var register = _.once(function () {
alert('Register ok!');
});
// 测试效果:
register();
register(); //之后无弹窗
register();
delay
'use strict';
// 2秒后调用alert():
_.delay(alert, 2000);
延迟调用的函数有参数:
var log = _.bind(console.log, console);
_.delay(log, 2000, 'Hello,', 'world!');
// 2秒后打印'Hello, world!':
Python
字符串编码
ord()
获取字符的整数表示,chr()
把编码转换为对应的字符:
>>> ord('A')
65
>>> ord('中')
20013
>>> chr(66)
'B'
>>> chr(25991)
'文'
用十六进制这么写str
:
>>> '\u4e2d\u6587' #4e2d>20013>'中'
'中文'
字符串类型为str
,在网络上传输或保存到磁盘需要转化为字节为单位的bytes
数据,用带b
前缀的单引号或双引号表示:'ABC'
和b'ABC'
不同。
encode()与decode()
str
通过encode()
方法可以编码为指定的bytes
:
>>> 'ABC'.encode('ascii')
b'ABC'
>>> '中文'.encode('utf-8')
b'\xe4\xb8\xad\xe6\x96\x87'
>>> '中文'.encode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
把bytes
变为str
,需要用decode()
:
>>> b'ABC'.decode('ascii')
'ABC'
>>> b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
'中文'
如果bytes
中只有一小部分无效的字节,可以传入errors='ignore'
忽略错误的字节:
>>> b'\xe4\xb8\xad\xff'.decode('utf-8', errors='ignore')
'中'
len()
计算str
的字符数用len()
:
>>> len('ABC')
3
>>> len('中文')
2
如果换成bytes
就计算字节数:
>>> len(b'ABC')
3
>>> len(b'\xe4\xb8\xad\xe6\x96\x87')
6
>>> len('中文'.encode('utf-8'))
6
占位符
x%
——十六进制整数;
%s
永远起作用,它会把任何数据类型转换为字符串:
>>> 'Age: %s. Gender: %s' % (25, True)
'Age: 25. Gender: True'
#format(), 占位符{0}、{1}…
>>> 'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)
'Hello, 小明, 成绩提升了 17.1%'
f-string, 若包含{xxx},就会以对应的变量替换:
>>> r = 2.5
>>> s = 3.14 * r ** 2
>>> print(f'The area of a circle with radius {r} is {s:.2f}')
The area of a circle with radius 2.5 is 19.62
除了特殊需求,牢记仅使用UTF-8编码。
list与tuple
list
>>> classmates = ['Michael', 'Bob', 'Tracy']
>>> classmates
['Michael', 'Bob', 'Tracy']
len()函数可以获得list元素的个数:len(classmates) //3
>>> classmates[0]
'Michael'
>>> classmates[1]
'Bob'
>>> classmates[2]
'Tracy'
>>> classmates[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
访问倒数第n个元素:
>>> classmates[-1]
'Tracy'
>>> classmates[-2]
'Bob'
>>> classmates[-3]
'Michael'
>>> classmates[-4]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
追加元素
#从末尾追加
>>> classmates.append('Adam')
>>> classmates
['Michael', 'Bob', 'Tracy', 'Adam']
#按索引插入
>>> classmates.insert(1, 'Jack')
>>> classmates
['Michael', 'Jack', 'Bob', 'Tracy', 'Adam']
#删除末尾
>>> classmates.pop()
'Adam'
>>> classmates
['Michael', 'Jack', 'Bob', 'Tracy']
#索引弹出
>>> classmates.pop(1)
'Jack'
>>> classmates
['Michael', 'Bob', 'Tracy']
#替换
>>> classmates[1] = 'Sarah'
>>> classmates
['Michael', 'Sarah', 'Tracy']
list套list——多维数组
>>> s = ['python', 'java', ['asp', 'php'], 'scheme']
>>> len(s)
4
tuple
理解“指向不变”:
>>> t = ('a', 'b', ['A', 'B'])
>>> t[2][0] = 'X'
>>> t[2][1] = 'Y'
>>> t
('a', 'b', ['X', 'Y'])
条件判断
if <条件判断1>:
<执行1>
elif <条件判断2>:
<执行2>
elif <条件判断3>:
<执行3>
else:
<执行4>
循环
for...in...
for x in ...
循环就是把每个元素代入变量x,然后执行缩进块的语句。
names = ['Michael', 'Bob', 'Tracy']
for name in names:
print(name)
range(101)
生成0-100的整数序列.
while
循环
sum = 0
n = 99
while n > 0:
sum = sum + n
n = n - 2
print(sum)
dict与set
dict在其他语言中Map对象。
总述: 列表 list[]
、元组 tuple()
、字典 dict{ key : value }
、无序不重复元素集合 set(list[])
,后两者的key为不可变对象, 元组元素"指向"不可变。
对于 不变对象 来说,调用对象自身的任意方法,也不会改变该对象自身的内容。相反,这些方法会创建新的对象并返回,这样,就保证了不可变对象本身永远是不可变的。
重复元素在set中自动被过滤:
>>> s = set([1, 1, 2, 2, 3, 3])
>>> s
{1, 2, 3}
添加元素到set
中:
>>> s.add(4)
>>> s
{1, 2, 3, 4}
>>> s.add(4)
>>> s
{1, 2, 3, 4}
删除元素:
>>> s.remove(4)
>>> s
{1, 2, 3}
set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:
>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s1 & s2
{2, 3}
>>> s1 | s2
{1, 2, 3, 4}
调用函数
max()
函数可以接受任意多个参数, 并返回最大的数:
>>> max(1, 2)
2
>>> max(2, 3, 1, -5)
3
定义函数
空函数
def nop():
pass
pass
可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass
,让代码能运行起来, 也可以放到其他语句中:
if age >= 18:
pass
参数检查
数据类型检查可以用内置函数isinstance()
实现:
def my_abs(x):
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x
返回多个值
游戏中经常需要从一个点移动到另一个点,给出坐标、位移和角度,就可以计算出新的坐标:
import math
def move(x, y, step, angle=0):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny
Python函数返回的仍然是单一值:
>>> r = move(100, 100, 60, math.pi / 6)
>>> print(r)
(151.96152422706632, 70.0)
函数的参数
明天