人生苦短系列中级篇 : python 进阶技巧

python --version : 3.7.0
update : 2018/09/24

六层标题备忘 : (一) / 1. / (1) / <1> / (i) /<i>

(一)编码问题

1. 'abc' 和 b'abc'

>>> 'abc'.encode()
b'abc'
>>> b'abc'.decode()
'abc'

python3有两种字符序列类型: "str"和"bytes" ,分别对应字符串的"文本状态"和"字节流状态"。
python3中的字符串使用Unicode字符集进行存储,当其类型为"str"时,直接输出会显示对应的文本状态; 而需要查看其对应的字节流(二进制)时,需要对"str"进行编码(encode),需要选择方案,如utf-8,GBK等(python3中默认编码方案为utf-8); 反之由"bytes"类型向"str"转换(decode)时,需要声明之前的编码方案。

>>> s = '中'
>>> type(s)
<class 'str'>
>>> sb = s.encode() # equal to "sb = s.encode(encoding = "utf-8")"
>>> sb
b'\xe4\xb8\xad'
>>> type(sb)
<class 'bytes'>
>>> sb.decode() # means "sb.decode(encoding = "utf-8")"
'中'

2. base64编码

3 str * 8 bit --> 4 str * 6 bit

>>> import base64
>>> base64.b64encode('Life is short, you need python.'.encode())
b'TGlmZSBpcyBzaG9ydCwgeW91IG5lZWQgcHl0aG9uLg=='
>>> base64.b64decode(b'TGlmZSBpcyBzaG9ydCwgeW91IG5lZWQgcHl0aG9uLg==')
b'Life is short, you need python.'

(二)数制转换

1. python中的整数

python中的整数不设上限,可任意大,处理起来非常方便。
python中的整数有4种常用的表示形式,分别为十进制,二进制,八进制,十六进制,其中二、八、十六进制的前缀分别为'0b'、'0o'、'0x',四种形式输入IDLE,都被解释为十进制整数,是一回事。

>>> 65
65
>>> 0b1000001
65
>>> 0o101
65
>>> 0x41
65

2. 拥有字符形式的整数

设整数的十进制形式为n, 当32<=n<=126时,其也可以表示可见字符的ASCII码,可与对应字符相互转换。

>>> chr(65)
'A'
>>> ord('A')
65

3.内置数制转换函数

可以将上述任意数制转换为二、八、十六进制的函数为bin(x),oct(x),hex(x),输出为str。

>>> bin(65)
'0b1000001'
>>> oct(65) #八进制对应的str无前缀
'0101'
>>> hex(65)
'0x41'
>>> hex(0b1000001)
'0x41'

4.其他数制转换方法

(1) 将任意数制(str)转换为十进制 : int('num', base)

这一函数常用于将str强制类型转换成int。

>>> int('0x41',16)
65
>>> int('41',16)
65
>>> int('41') #默认base = 10
41

(2) 不带前缀的格式化输出 : "{:base}".format(x)

>>> "{:b}".format(65)
'1000001'
>>> "{:x}".format(65)
'41'
>>> "{:o}".format(65)
'101'

5.字符串转字节流

(1) binascii.hexlify()

有时需要将字符串与对应的十六进制字节流相互转换(如rtf文档的构造或解析), 使用自带库binascii的函数可轻松解决。

>>> import binascii
>>> binascii.hexlify(b'abc')
b'616263'
>>> binascii.unhexlify(b'616263')
b'abc'
>>> binascii.b2a_hex(b'abc')
b'616263'
>>> binascii.a2b_hex(b'616263')
b'abc'

hexlify()和b2a_hex()都可将字符串转为16进制字节流,
unhexlify()和a2b_hex()都可将16进制字节流转为字符串。

(2) python2的技巧(python3不适用)

在python2中一行代码即可搞定,注意此方法在python3中会报错("hex"编解码器已被删除)。

>>> "abc".encode("hex")
'616263'
>>> '616263'.decode("hex")
'abc'

(三)输入输出

1. 格式化输出需加括号

print("My name is %s" %("yourDaddy"))

2. 格式化输出字符串的两种方式

(1) %

>>> n = 123
>>> s = "%d" % n # 等价于强制类型转换 s = str(n)
>>> s
'123'

(2) .format

<1> 常规填充

>>> "{} - {} cm".format('sandy',18)
'sandy - 18 cm'

<2> 数制转换

>>> '{:b}'.format(18) # to 2
'10010'
>>> '{:x}'.format(18) # to 16
'12'

2. python3 取消了raw_input, 但还可以用input接收输入

>>>message = input()
123
>>> message
'123'

3. sys.stdin.read()可以实现标准输入, IDLE下"enter + ctrl + d"可终止输入(linux下同样适用),windows cmd下为"enter + ctrl + z + enter"

>>>import sys
>>>s=sys.stdin.read()
123

>>>s
'123\n'

(四)命令行下输入参数的处理技巧

1. 获取命令行下输入的参数 : sys.argv

命令行下执行py脚本,后加一堆参数,则用sys.argv可将这些参数以列表形式存储,每个参数都是"str"类型,且列表首元素sys.argv[0] = "pythonFileName"(列表长度 = 输入参数 + 1)。

#test.py
import sys
parse = sys.argv
print(parse)

---

shell > test.py 1 2 3
['C:\\Users\\Administrator\\Desktop\\python3\\test.py','1','2','3']
shell > 

2. 带选项的输入 : getopt库

(1) 短选项模式

#getoptShortMode.py
import getopt
inputt = '-n cos -e -d 18cm add'.split()
print("Input: %s" % (inputt))
opts, args = getopt.getopt(inputt, 'n:ed:')
print("opts: %s" % (opts))
print("args: %s" % (args))

---

shell > getoptShortMode.py
Input: ['-n', 'cos',  '-e', '-d', '18cm', 'add']
opts: [('-n', 'cos'), ('-e', ''), ('-d', '18cm')]
args: ['add']

短选项模式假定py文件后面跟的都是形如"-选项 参数"的格式,其中"选项"为单字母(这就是为什么叫短选项),"参数"可以为空;
短模式函数引用形式为opts,args = getopt(input,shortOpts),input就是输入的"选项-参数"流,上例中的shortOpts = "n:ed:", 其首先将所有选项的字母收集进来,选项后如果有参数,则选项后跟冒号(如"n:"),否则不跟(如"e");
getopt依据shortOpts的规则将Input分成tuple,存入opts,Input中没在shortOpts中出现的部分划到args里。

注意shortopts里选项的顺序不一定非要和input里的选项顺序一致,最后opts里tuple的顺序是跟input里选项出现的先后顺序一致;
但没有选项的参数(如'add')一定要放到最后,否则其后的选项不被识别。

(3) 长选项模式

#getoptLongMode.py
import getopt
inputt = '--name=cos --dick=18cm --r unkown'.split()
print("Input: %s" % (inputt))
opts, args = getopt.getopt(inputt, '', ['name=', 'dick=', 'r'])
print("opts: %s" % (opts))
print("args: %s" % (args))
---
shell > getoptLongMode.py
Input: ['--name=cos', '--dick=18cm', '--r', 'unkown']
opts: [('--name', 'cos'), ('--dick', '18cm'), ('--r', '')]
args: ['unkown']

长选项假定后面跟的都是形如"--选项=参数"或"--选项"的格式,注意shortOpt=''

(3) 混合模式

#mixMode.py
import getopt
inputt = '--name=cos -f handsome --rich --dick=18cm -h 185 -r add unkown'.split()
opts, args = getopt.getopt(inputt, 'f:rh:', ['name=', 'rich', 'dick='])
print("input: %s " % (inputt))
print("opts: %s " % (opts))
print("args: %s " % (args))
---
shell > mixMode.py
input: ['--name=cos', '-f', 'handsome', '--rich', '--dick=18cm', '-h', '185', '-r', 'add', 'unkown'] 
opts: [('--name', 'cos'), ('-f', 'handsome'), ('--rich', ''), ('--dick', '18cm'), ('-h', '185'), ('-r', '')] 
args: ['add', 'unkown']
shell > 

3. 自动生成使用帮助 : argparse库

python 2.7以后弃用optparse模块,改用argparse替代。

(1) 用法

#test2.py
import argparse
parser = argparse.ArgumentParser(description = "argparse test")
parser.add_argument("-t", help="target IP")
cmdInput = parser.parse_args()
---
shell> test2.py -h
usage: test2.py [-h] [-t T]

argparse test

optional arguments:
  -h, --help  show this help message and exit
  -t T        target IP

命令行下输入".py文件" + "-h"自动生成用法帮助信息;
关键函数是add_args,其向命令行添加输入选项,帮助信息存放于help参数中(当然也可以不要)。

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument("-t")
_StoreAction(option_strings=['-t'], dest='t', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)

(2) add_args函数参数详解

<1> 可选参数 : option_strings = "-t" 或 option_strings = "-p", "--port"

用法: shell> test2.py -p 4444shell>test2.py --port 4444

#test2.py
import argparse
parser = argparse.ArgumentParser()

parser.add_argument("-t")
parser.add_argument("-p","--port")

cmdInput = parser.parse_args()
print("target input: %s %s" % (cmdInput.t,type(cmdInput.t)))
print("port input: %s" % (cmdInput.port)


shell>test2.py -t 127.0.0.1 --port 4444
target input: 127.0.0.1 <class 'str'>
port input: 4444 

当指定选项名为形如"-t"这样的短选项时,后面跟的具体参数会以字符串类型保存于"parse_args().t"中;
而当选项名为"-p"+"--port"长短结合的形式,参数会保存于"parse_args().port"中,当然长短形式的选项都可以使用。

<2> 位置参数 : option_strings = "target"

用法: shell> test2.py 127.0.0.1

#test2.py
import argparse
parser = argparse.ArgumentParser()

parser.add_argument("target")

cmdInput = parser.parse_args()
print("target: %s " % (cmdInput.target))

---
shell> test2.py 127.0.0.1
target: 127.0.0.1

使用位置参数时,无需输入选项,直接输入参数,参数会保存在"parse_args().target"中。

<3> 不需要参数的选项 : action = "store_true"

用法: shell> test2.py -t

#test2.py
import argparse
parser = argparse.ArgumentParser()

parser.add_argument("-t", action="store_true")

cmdInput = parser.parse_args()
print(cmdInput.t)
print(type(cmdInput.t))

---
shell> test2.py -t
True
<class 'bool'>

参数action是用来处理当捕获到输入参数后下一步的动作,默认为 action = "store",即将参数保存到指定变量;
action = "store_true"表示选项后无需输入参数,默认参数为bool型的"True",将其存入变量中。

<4> 其他参数

  • type = int : 函数默认输入参数保存为字符类型,使用type可将输入参数保存为其他类型。
  • required = True : 默认该参数为"False",赋值后选项变为必须输入项,不输入则报错

(五)进程处理技巧

1. 进程中开启多线程 : threading库

  • 进程(process)就是一个应用程序的一次执行过程,线程(thread)是进程中执行运算的最小单位。
  • 操作系统把资源分配给进程,而线程可以在其中独立运行和调度。
  • 一个进程可以有多个线程,一个线程必须属于某个进程。
  • 若一个进程是单线程的,若此进程要执行三个任务,则只能串行执行(即单线程按任务顺序依次执行);多线程是指若一进程有三个线程,要执行三个任务,则三个线程可同时并行处理(CPU在同一时间只能处理一条线程,之所以可以多线程并行处理CPU在多条线程间可以快速切换,造成了同时进行的假象)。

(1) 用法

#Usage:
import threading
threadd = threading.Thread(target = function, args = (funcParameter1,funcParameter1)) #create thread,execute target(function) with/without arguments
threadd.start()

(2) 简单示例

#multiThread.py
import threading

def printNum(Num,Counts):
    for i in range(Counts):
        print(str(Num)*Counts)

counts = 5
thread1 = threading.Thread(target = printNum, args = (1,counts))
thread2 = threading.Thread(target = printNum, args = (0,counts))
thread1.start()
thread2.start()

---
========== RESTART: C:\Users\Administrator\Desktop\python3\multiThread.py ==========
11111
11111
1111100000
>>> 

11111
11111
00000
00000
00000
00000

2. 由窗口到进程 : ctypes.windll.user32.GetWindowThreadProcessId()

  • PID : 进程在被创建时系统内核会为其分配一个固定不变的序列号(PID),供函数或其他进程调用,进程终止后会被回收进行二次分配。
  • 进程句柄(号) : 是指针,动态变化,当访问该进程时得到,用完必须释放。
  • 窗口 : 一个进程可以有多个窗口(想象firefox.exe开两个窗口上网),窗口也有对应的窗口句柄(号)供系统调用,同样是指针,每次调用也动态变化。
#tryCtypes.py
import ctypes

#get window handle
handle = ctypes.windll.user32.GetForegroundWindow()

#get window title
windowTitle = ctypes.create_string_buffer(("\x00" * 512).encode())
length = ctypes.windll.user32.GetWindowTextA(handle, ctypes.byref(windowTitle), 512)

#get PID
pid = ctypes.c_ulong(0)
ctypes.windll.user32.GetWindowThreadProcessId(handle, ctypes.byref(pid))

#get process name
peName = ctypes.create_string_buffer(("\x00" * 512).encode())
hProcess = ctypes.windll.kernel32.OpenProcess(0x400 | 0x10, False, pid)
ctypes.windll.psapi.GetModuleBaseNameA(hProcess,None, ctypes.byref(peName), 512)

kernel32.CloseHandle(handle)
kernel32.CloseHandle(hProcess)


print("[*] current window:")
print("[*] window handle: %s" % handle)
print("[*] pid(process ID): %s" % pid.value)
print("[*] process name: %s" % peName.value.decode())
print("[*] window title: %s" % windowTitle.value.decode())

---
>>> 
========== RESTART: C:\Users\Administrator\Desktop\python3\tryCtypes.py ==========
[*] current window:
[*] window handle: 2360406
[*] pid(process ID): 4172
[*] process name: pythonw.exe
[*] window title: *Python 3.7.0 Shell*
>>> 

(六) windows进阶

1. windows消息机制和钩子 : pyHook库

(1) windows的窗口程序基于消息机制,并由事件驱动。

  • 事件(event) : 事件是由用户通过外部输入设备触发的动作,如点击鼠标左键,敲击键盘都会产生一个事件。
    (除此之外事件还可能由诸如button控件、file菜单触发,也有来自windows内部的事件)
  • 消息(message) : 事件产生消息。当一个事件被触发后,会被windows翻译(量化)成一个消息。
    消息是一个结构体数据,里面包含窗口句柄(消息所属窗口),消息编号,和两个DWORD消息参数。
  • windows消息机制
    <1> 当用户运行一个应用程序时,通过点击鼠标或者敲键盘,产生了一些事件;
    <2> 事件被windows监控到,量化为消息,消息被windows捕获到之后放到windows的消息队列;
    <3> windows在分析该消息之后得知它应该属于哪个应用程序,就把它存到该程序自己的消息队列中;
    <4> 每个程序都有一个消息循环,不断从自己的消息队列中读取消息,并将其分配给相应的线程或窗口,交由窗口处理函数处置。

(2) 钩子(函数)

  • 前文提到,当一个消息被windows分析之后要发往相应程序的消息队列。
    钩子就是(在消息被发往程序的消息队列之前)截获消息的函数。
  • windows的原生函数SetWindowsEx允许我们自定义钩子,从而去截获特定事件生成的消息。
    pyHook库就是基于这一函数进行封装编写的。
  • pyHook是第三方库,但无法pip快捷安装。
    [pyHook下载地址]
    下载完成后输入pip install xxx.whl安装即可。
    注意64位windows7下安装的python有可能是32位的(使用platform.architecture()查看python架构)。

(3) 应用 : 键盘/鼠标记录

#example.py
import pyHook

def OnMouseEvent(event):
    print('MessageName:',event.MessageName)
    print('Message:',event.Message)
    print('Time:',event.Time)
    print('Window:',event.Window)
    print('WindowName:',event.WindowName)
    print('Position:',event.Position)
    print('Wheel:',event.Wheel)
    print('Injected:',event.Injected)
    print('---')

    # return True to pass the event to other handlers
    # return False to stop the event from propagating
    return True

def OnKeyboardEvent(event):
    print('MessageName:',event.MessageName)
    print('Message:',event.Message)
    print('Time:',event.Time)
    print('Window:',event.Window)
    print('WindowName:',event.WindowName)
    print('Ascii:', event.Ascii, chr(event.Ascii))
    print('Key:', event.Key)
    print('KeyID:', event.KeyID)
    print('ScanCode:', event.ScanCode)
    print('Extended:', event.Extended)
    print('Injected:', event.Injected)
    print('Alt', event.Alt)
    print('Transition', event.Transition)
    print('---')

    # return True to pass the event to other handlers
    # return False to stop the event from propagating
    return True

# create the hook mananger
hm = pyHook.HookManager()
# register two callbacks
hm.MouseAllButtonsDown = OnMouseEvent
hm.KeyDown = OnKeyboardEvent

# hook into the mouse and keyboard events
hm.HookMouse()
hm.HookKeyboard()

if __name__ == '__main__':
    import pythoncom
    pythoncom.PumpMessages()

---

>>> 
 RESTART: C:\Program Files (x86)\Python37-32\Lib\site-packages\pyHook\example.py 
MessageName: mouse left down
Message: 513
Time: 179313024
Window: 65680
WindowName: Running applications
Position: (278, 1015)
Wheel: 0
Injected: 0
---
MessageName: key down
Message: 256
Time: 179317158
Window: 1312710
WindowName: Administrator: Command Prompt
Ascii: 73 I
Key: I
KeyID: 73
ScanCode: 23
Extended: 0
Injected: 0
Alt 0
Transition 0


2. 设备描述表(未完待续)

  • windows显示原理 : 用户操作 --> 设备描述表 --> 显卡驱动程序 --> 显卡硬件 --> 显示器

  • 设备描述符(Device Context, DC) : 又称设备上下文,用以实现应用程序与硬件之间的交互。

  • DC是一种数据结构,其结构的核心是位图(bitmap)。

  • GDI(Graphics Device Interface, 图形设备接口) ?
    DC是GDI函数内部保留的数据结构

  • 应用 : 屏幕快照
#pywin32 library
import win32gui
import win32ui
import win32con
import win32api

#1.获取当前桌面的句柄和像素尺寸
hdesktop = win32gui.GetDesktopWindow() 

width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN)
height = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN)
left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN)
top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN)

#2.获取当前桌面的设备描述表,用以创建截图用的设备描述表
desktopDC = win32gui.GetWindowDC(hdesktop)
imgDC = win32ui.CreateDCFromHandle(desktopDC)

memDC = imgDC.CreateCompatibleDC()

screenshot = win32ui.CreateBitmap()
screenshot.CreateCompatibleBitmap(imgDC, width, height)

memDC.SelectObject(screenshot)

memDC.BitBlt((0, 0), (width, height), imgDC, (left, top), win32con.SRCCOPY)
screenshot.SaveBitmapFile(memDC, 'C:\\Users\\Administrator\\Desktop\\screenshot.bmp')

memDC.DeleteDC()
win32gui.DeleteObject(screenshot.GetHandle())
python实现全屏截图(两个程序对比着看,继续学习这部分内容)
import time
import os, win32gui, win32ui, win32con, win32api

def window_capture():
    hwnd = 0
    hwndDC = win32gui.GetWindowDC(hwnd)
    mfcDC=win32ui.CreateDCFromHandle(hwndDC)
    saveDC=mfcDC.CreateCompatibleDC()
    saveBitMap = win32ui.CreateBitmap()
    MoniterDev=win32api.EnumDisplayMonitors(None,None)
    w = MoniterDev[0][2][2]
    h = MoniterDev[0][2][3]
    print w,h
    saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)
    saveDC.SelectObject(saveBitMap)
    saveDC.BitBlt((0,0),(w, h) , mfcDC, (0,0), win32con.SRCCOPY)
    bmpname=win32api.GetTempFileName(".","")[0]+'.bmp'
    saveBitMap.SaveBitmapFile(saveDC, bmpname)
    return bmpname

os.system(window_capture())

3. pywin32库(pip)

import pythoncom
import win32clipboard


4. ctypes库


5. 命令行下与shell交互的处理技巧

(1) 如何与命令行交互(脚本命令放入命令行执行,结果返回)

(2) subprocess库


(七)导入模块的三种方法的区别

1. import module

方法型引用

>>> import math
>>> math.pi
3.141592653589793

2. from module import *

将模块下所有名字引入当前名称空间,直接引用。

>>> from math import *
>>> pi
3.141592653589793

3. import module as xxx

用xxx来代替module进行引用

>>> import math as m
>>> m.pi
3.141592653589793

(八)待研究问题

1.深拷贝与浅拷贝

  1. !!!!!!!!!!!! 类 class !!!!!
  2. py文件封装成exe : XXX库
  3. 爬虫
  4. GUI编程 : PyQt
  5. json
  6. 正则表达式
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容

  • 一、Python简介和环境搭建以及pip的安装 4课时实验课主要内容 【Python简介】: Python 是一个...
    _小老虎_阅读 5,688评论 0 10
  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,242评论 8 265
  • 最近听书或阅读关于“幸福是种能力”出现的频率很高,我自己的体会也是这样,其实我们身边充满了美好,不管是温暖的阳光还...
    作家阿紫阅读 633评论 4 1
  • 麦客的样子 和你差不多 麦客弯腰割麦 麦客的刀 锋芒毕露 麦客往麦地一站 麦地 疯长大片大片的收获 麦...
    雪山孟龙阅读 296评论 0 0
  • 作者:松冈达英 译:蒲蒲兰 推荐理由: 大人们可能会觉得如此简单的绘本太没有意思了,可是对于孩子越简单越喜欢,书中...
    那一日阅读 361评论 0 0