Python:数字、字符串和变量

变量,名字和对象

Python 最基本的内置数据类型包括:
• 布尔型(表示真假的类型,仅包含 True 和 False 两种取值)
• 整型(整数,例如 10、100000)
• 浮点型(小数,例如 3.14,或用科学计数法表示的数字,例如 1.0e6,它表示 1 乘以 10 的 6 次方,也可写作 1000000.0)
• 字符串型(字符组成的序列)

Python 里所有数据——布尔值、整数、浮点数、字符串,甚至大型数据结构、函数以及程序——都是以对象(object)的形式存在的。

可以把对象看作一个盒子,里面装着数据。对象有不同类型,例如整形和浮点型等。类型决定了可以对它进行的操作还决定了它存放的数据是可修改的(可变的)还是不可修改的(不可变的)。可以把不可变对象看作一个密闭的透明盒子:你可以看到里面的数据,但无法修改它。同理,可以把可变对象看作一个透明可以打开的盒子:你可以打开盒子修改里面的数据。但无法改变这个盒子本身,就是无法改变对象的类型。

变量就是在程序中为了方便地引用内存中的值而为它取的名称。在python中使用=来为变量赋值。下面这段代码首先将整数 1 赋值给了变量 a,之后又将 a 的值打印了出来:

>>> a=1
>>> print(a)
1

要注意赋值操作并不会实际复制值,它只是为数据对象取个相关的名字。名字是对对象的引用而不是对象本身。可以把它想象贴成盒子上的标签。


图片1.png

如果我们将a赋值给b,这相当于把a标签撕下换上b标签。但盒子里的数据是不变的。

>>> b=a
>>> print(b)
1

在 Python 中,如果想知道一个对象(例如一个变量或者一个字面值)的类型,可以使用语句:type( thing )。例如:

>>> type(a)
<class 'int'>
>>> type(b)
<class 'int'>
>>> type(10)
<class 'int'>
>>> type(10.1)
<class 'float'>
>>> type('abc')
<class 'str'>

变量名只能包含以下字符:
• 小写字母(a~z)
• 大写字母(A~Z)
• 数字(0~9)
• 下划线(_)
名字不允许以数字开头。以下划线开头的名字有特殊的含义。不要使用下面这些词作为变量名,它们是 Python 保留的关键字:

关键字
False class finally is return
None continue for lambda try
True def from nonlocal while
and del global not with
as elif if or yield
assert else import pass break
except in raise

这些关键字以及其他的一些标点符号是用于描述 Python 语法的。

数字

Python 本 身 支 持 整 数( 比 如 1 和 1000000000) 以 及 浮 点 数( 比 如 3.14、1.99 和1.87e3)。你可以对这些数字进行下表中的计算。

运算符 描述 示例 运算结果
+ 加法 1 + 1 2
- 减法 2 – 1 1
* 乘法 1 * 2 2
/ 浮点数除法 3 / 2 1.5
// 整数除法 3 // 2 1
% 求余 3 % 2 1
** 次方 3 ** 3 27

整数

可以定义1个正整数可以加+号也可以不加,也可以前面加一个-号变为负数。可以使用数字0,但它不能作为前缀放在其它数字后。

>>> 123
123
>>> +123
123
>>> -123
-123
>>> 0
0
>>> 01
  File "<stdin>", line 1
    01
     ^
SyntaxError: invalid token

可以使用运算符号来进行python的常规运算:

#  #号是对代码的注释,是用来对代码执行的部分进行说明,程序不执行前面有#号的代码
>>> 5 + 1
6
>>> 100 - 7
93  
>>> 4 - 10
-6
>>> 10 + 9 + 3
22
>>> 4 + 3 - 2 - 1 + 6
10
#格式提示:数字和运算符之间的空格不是强制的,你也可以写成下面这种格式:
>>> 5+9 + 3
17
#只不过添加空格会使代码看起来更工整。
>>> 5 * 3
15
>>> 3 * 5
15
>>> 3 * 5 * 2
30

Python 里有两种除法:
• / 用来执行浮点除法(十进制小数)
• // 用来执行整数除法(整除)
即使运算对象是两个整数,使用 / 仍会得到浮点型的结果:

>>> 9 / 5
1.8
#使用整除运算得到的是一个整数,余数会被截去:
>>> 9 // 5
1
#如果除数为 0,任何一种除法运算都会产生 Python 异常:
>>> 5 / 0
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> 7 // 0
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by z

也可以用数字赋值变量来进行运算:

>>> a=9
>>> a
9
>>> a-3
6
#上面代码中出现了 a - 3,但并没有将结果赋值给 a,因此 a 的值并未发生改变:
>>> a
9
#如果想要改变 a 的值,可以这样写:
>>> a = a - 3
>>> a
6

也可以先计算a-3的值,将运算结果保存在一个临时变量中,再将这个临时变量的值赋回给a:

>>> a = 9
>>> temp = a - 3
>>> a = temp

当然也可以进一步简化,将运算和赋值过程合并。例如, a -= 3 等价与 a = a - 3,以此类推a += 9 等价于a = a + 9等等:

>>> a = 9
>>> a -= 3
>>> a
6
>>> a += 9
>>> a
15
>>> a *= 2
>>> a
30
>>> a /= 9
>>> a
3.3333333333333335
>>> a = 13
>>> a //= 4
>>> a
3

优先级

在使用python运算符时要遵循运算符的优先级,优先级高的先运行。例如:

>>> 1 / 2 + 3 * 4
12.5

/ 和 * 具有相同的优先级并且高于 + 的优先级,就和数学运算一样先有乘除,后算加减。如果想要先算加减,可以和数学运算一样使用括号。

>>> 1 / (2 + 3) * 4
0.8

下面这张表是官方文档中关于优先级的混合,高优先级的运算符在上面。

操作符 描述和示例
[v1, ...]、{v1, ...}、{k1: v1, ...}、(...) 列表 / 集合 / 字典 / 生成器的创建和推导,括号内表达式
seq[n]、seq[n:m]、func(args...)、obj .attr 索引、切片、函数调用和属性引用
** 幂运算
+x、-x、~x 正号、负号和位求反
*、/、//、% 乘法、浮点除法、整数除法和取余
+、- 加法、减法
<<、>> 按位左移、按位右移
& 按位与
| 按位或
in、not in、is、is not、<、<=、>、>=、!=、== 属于关系和相等性测试
not x 布尔取非
and 布尔取与
or 布尔取或
if...else 条件表达式
lambda lambda 表达式

类型转换

在Python当中可以使用int()函数将其他数据类型转换为整数,它会保留传入数据的整数部分,并舍去小数部分。
Python 里最简单的数据类型是布尔型,它只有两个可选值:True 和 False。当转换为整数时,它们分别代表 1 和 0:

>>> int(True)
1
>>> int(False)
0

当将浮点数转换为整数时,所有小数点后面的部分会被舍去:

>>> int(18.6)
18
>>> int(1.0e3)
1000

也可以将仅包含数字和正负号的字符串转换为整数,下面有几个例子:

>>> int('99')
99
>>> int('-23')
-23
>>> int('+12')
12

将一个整数转换为整数没有太多意义:

>>> int(12345)
12345

如果将一个与数字无关的类型转化为整数,会得到一个异常:

>>> int('I am batman')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'I am batman'
>>> int('')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: ''
>>> int('5batman')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '5batman'

尽管上面例子中的字符串的确是以有效数字(5)开头的,但它没有就此截止,后面的内容不是纯数字,无法被 int() 函数识别,因此抛出异常。

int() 可以接受浮点数或由数字组成的字符串,但无法接受包含小数点或指数的字符串:

>>> int('98.6')
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '98.6'
>>> int('1.0e3')
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '1.0e3'

如果混合使用多种不同的数字类型进行计算,Python 会自动地进行类型转换:

>>> 4 + 7.0
11.0

与整数或浮点数混合使用时,布尔型的 False 会被当作 0 或 0.0,Ture 会被当作 1 或 1.0:

>>> True + 2
3
>>> False + 5.0
5.0

浮点数

整数全部由数字组成,而浮点数(在 Python 里称为 float)包含非数字的小数点。
使用 float() 函数可以将其他数字类型转换为浮点型。与之前一样,布尔型在计算中等价于 1.0 和 0.0:

>>> float(True)
1.0
>>> float(False)
0.0

将整数转换为浮点数仅仅需要添加一个小数点:

>>> float(98)
98.0
>>> float('99')
99.0

此外,也可以将包含有效浮点数(数字、正负号、小数点、指数及指数的前缀 e)的字符串转换为真正的浮点型数字:

>>> float('98.6')
98.6
>>> float('-1.5')
-1.5
>>> float('1.0e3')
1000.0

字符串

Python 字符串是不可变的。你无法对原字符串进行修改,但可以将
字符串的一部分复制到新字符串,来达到相同的修改效果。

使用引号创建

将一系列字符包裹在一对单引号或一对双引号中即可创建字符串,就像下面这样:

>>> 'XSS'
'XSS'
>>> "SQL"
'SQL'

解释器输出的字符串永远是用单引号包裹的,但无论使用哪种引号,Python 对字符串的处理方式都是一样的,没有任何区别。
既然如此,为什么要使用两种引号?这么做的好处是可以创建本身就包含引号的字符串,而不用使用转义符。可以在双引号包裹的字符串中使用单引号,或者在单引号包裹的字符串中使用双引号:

>>> "hello 'world'."
"hello 'world'."
>>> 'hello "world".'
'hello "world".'

也可以使用连续三个单引号 ''',或者三个双引号 """ 创建字符串:

>>> '''sql'''
'sql'
>>> """sql"""
'sql'

三引号在创建短字符串时没有什么特殊用处。它多用于创建多行字符串。下面的例子我们来创建一个多行字符串:

>>> Weather_Control = '''Lightling storm ready
... Warning:lightling storm created
... '''
>>>

(上面这段代码是在交互式解释器里输入的,第一行的提示符为 >>>,后面行的提示符为 ...,直到再次输入三引号暗示赋值语句的完结,此时光标跳转到下一行并再次以 >>>提示输入。)
如果通过单独的单双引号创建多行字符串,在输入第一行并按下回车时,Python会弹出错误提示:

>>> Weather_Control = 'Lightling storm ready
  File "<stdin>", line 1
    Weather_Control = 'Lightling storm ready
                                           ^
SyntaxError: EOL while scanning string literal

在引号包裹的字符串中,每行的换行符以及行首或行末的空格都会被保留:

>>> Weather_Control = '''Lightling storm ready
...             Warning:lightling storm created
... '''
>>> print(Weather_Control)
Lightling storm ready
                Warning:lightling storm created

>>>

值得注意的是,print() 函数的输出与交互式解释器的自动响应输出存在一些差异:

>>> Weather_Control
'Lightling storm ready\n\t\tWarning:lightling storm created\n'

print() 会把包裹字符串的引号截去,仅输出其实际内容,易于阅读。它还会自动地在各个输出部分之间添加空格,并在所有输出的最后添加换行符:

>>> print('This', 1, 'car')
This 1 car

Python 允许空字符串的存在,它不包含任何字符且完全合法。可以使用前面提到的任意一种方法创建一个空串:

>>> ''
''
>>> ""
''
>>> ''''''
''
>>> """"""
''

为什么会用到空字符串?有些时候你想要创建的字符串可能源自另一字符串的内容,这时需要先创建一个空字符串。

>>> stature = 188
>>> weight = 95
>>> batman = ''
>>> batman += 'stature:'
>>> batman += str(stature)
>>> batman += ','
>>> batman += 'weight:'
>>> batman += str(weight)
>>> batman
'stature:188,weight:95'

使用str()进行类型转换

使用 str() 可以将其他 Python 数据类型转换为字符串:

>>> str(98.6)
'98.6'
>>> str(1.0e3)
'1000.0'
>>> str(True)
'True'

使用\转义

Python 允许你对某些字符进行转义操作,在字符的前面添加反斜线符号 \ 会使该字符的意义发生改变。最常见的转义符是 \n,它代表换行符,便于在一行内创建多行字符串。

>>> StarCraft =  'Protoss\nZerg\nTerran'
>>> print(StarCraft)
Protoss
Zerg
Terran

转义符 \t(tab 制表符)常用于对齐文本:

>>> print('\tabc')
        abc
>>> print('a\tbc')
a       bc
>>> print('ab\tc')
ab      c
>>> print('abc\t')
abc

(上面例子中,最后一个字符串的末尾包含了一个制表符,当然你无法在打印的结果中看到它。)
有时你可能还会用到 ' 和 " 来表示单、双引号,尤其当该字符串由相同类型的引号包裹时:

>>> batman = "\"Because I am batman\""
>>> print(batman)
"Because I am batman"
>>> batman = "\'Because I am batman\'"
>>> print(batman)
'Because I am batman'

如果需要输出一个反斜线字符,连续输入两个反斜线即可:

>>> print('hahaha \n')
hahaha

>>> print('hahaha \\n')
hahaha \n

python字符串格式化

Python 支持格式化字符串的输出 。最基本的用法是将一个值插入到一个有字符串格式符 %s 的字符串中。

占位符 替换内容
%d 整数
%f 浮点数
%s 字符串
>>> 'hello %s' %'world'
'hello world'
>>> 'Π = %.2f' % 3.14159  # %.2f是保留两位小数
'Π = 3.14'
>>> 'xiaoming is %d years old' % 10
'xiaoming is 10 years old'

使用+拼接

在 Python 中,你可以使用 + 将多个字符串或字符串变量拼接起来,就像下面这样:

>>> 'Because ' + 'I am batman'
'Because I am batman'

也可以直接将一个字面字符串(非字符串变量)放到另一个的后面直接实现拼接:

>>> 'Because ' 'I am batman'
'Because I am batman'

进行字符串拼接时,Python 并不会自动添加空格。但当调用print() 进行打印时,Python 会在各个参数之间自动添加空格并在结尾添加换行符:

>>> a = 'ha.'
>>> b = a
>>> c = 'haha!'
>>> a + b + c
'ha.ha.haha!'
>>> print(a,b,c)
ha. ha. haha!

使用*复制

使用 * 可以进行字符串复制:

>>> a = 'Ha ' * 3 + '\n'
>>> b = 'Xi ' * 3 + '\n'
>>> c = 'Bye.'
>>> print(a + b + c)
Ha Ha Ha
Xi Xi Xi
Bye.

使用[ ]提取字符

在字符串名后面添加 [],并在括号里指定偏移量可以提取该位置的单个字符。第一个字符(最左侧)的偏移量为 0,下一个是 1,以此类推。最后一个字符(最右侧)的偏移量也可以用 -1 表示,这样就不必从头数到尾。偏移量从右到左紧接着为 -2、-3,以此类推。


图片1.png
>>> str = '12345'
>>> str[0]
'1'
>>> str[1]
'2'
>>> str[-1]
'5'

如果指定的偏移量超过了字符串的长度会得到一个异常提醒:

>>> str[10]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: string index out of range

位置索引在其他序列类型(列表和元组)中的使用也是如此,由于字符串是不可变的,因此你无法直接插入字符或改变指定位置的字符。看看当我们试图将 'abc' 改变为 'bbc' 时会发生什么:

>>> name = 'abc'
>>> name[0] = 'b'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

为了改变字符串,我们需要组合使用一些字符串函数,例如 replace(),以及分片操作:

>>> name = 'abc'
>>> name.replace('a', 'b')
'bbc'
>>> 'b' + name[1:]
'bbc'

使用[start:end:step]分片

分片操作(slice)可以从一个字符串中抽取子字符串(字符串的一部分)。我们使用一对方
括号、起始偏移量 start、终止偏移量 end 以及可选的步长 step 来定义一个分片。其中一
些可以省略。分片得到的子串包含从 start 开始到 end 之前的全部字符。
• [:] 提取从开头到结尾的整个字符串
• [start:] 从 start 提取到结尾
• [:end] 从开头提取到 end - 1
• [start:end] 从 start 提取到 end - 1
• [start:end:step] 从 start 提取到 end - 1,每 step 个字符提取一个
与之前一样,偏移量从左至右从 0、1 开始,依次增加;从右至左从 -1、-2 开始,依次减
小。如果省略 start,分片会默认使用偏移量 0(开头);如果省略 end,分片会默认使用
偏移量 -1(结尾)。
我们来创建一个由小写字母组成的字符串:

>>> words = 'abcdefghijklmnopqrstuvwxyz'

使用 : 分片等价于使用 0 : -1(也就是提取整个字符串):

>>> words[:]
'abcdefghijklmnopqrstuvwxyz'

下面是一个从偏移量 10 提取到字符串结尾的例子:

>>> words[10:]
'klmnopqrstuvwxyz'

从偏移量 10 提取到15:

>>> words[10:15]
'klmno'

提取最后 3 个字符:

>>> words[-3:]
'xyz'

下面一个例子提取了从偏移量为 18 的字符到倒数第 3 个字符:

>>> words[18:-2]
'stuvwx'

提取从倒数第 6 个字符到倒数第 2 个字符:

>>> words[-6:-2]
'uvwx'

如果需要的步长不是默认的 1,可以在第二个冒号后面进行指定,就像下面几个例子所示。
从开头提取到结尾,步长设为 6:

>>> words[::6]
'agmsy'

从偏移量 5 提取到偏移量 19,步长设为 3:

>>> words[5:20:3]
'filor'

从偏移量 20 提取到结尾,步长设为 5:

>>> words[20::5]
'uz'

(分片中 end 的偏移量需要比实际提取的最后一个字符的偏移量多 1。)
如果指定的步长为负数,Python 还会从右到左反向进行提取操作。下面这个例子便从右到左以步长为 1 进行提取:

>>> words[-1::-1]
'zyxwvutsrqponmlkjihgfedcba'

还可以简写:

>>> words[::-1]
'zyxwvutsrqponmlkjihgfedcba'

分片操作对于无效偏移量的容忍程度要远大于单字符提取操作。在分片中,小于起始位置的偏移量会被当作 0,大于终止位置的偏移量会被当作 -1,就像接下来几个例子展示的一样。
提取倒数 30 个字符:

>>> words[-30:]
'abcdefghijklmnopqrstuvwxyz'

提取从倒数第 31 到倒数第 30 个字符:

>>> words[-31:-30]
''

从开头提取到偏移量为 31 的字符:

>>> words[:30]
'abcdefghijklmnopqrstuvwxyz'

从偏移量为 30 的字符提取到偏移量为 31 的字符:

>>> words[30:31]
''

python字符串函数

python有许多的内置字符串函数,可以去搜索python的字符串函数。这里使用几种常见的字符串函数来举例。

使用len()获取字符串长度

>>> a = 'abcdef'
>>> len(a)
6

使用split()分割

字符串函数 split() 可以基于分隔符将字符串分割成由若干子串组成的列表。列表(list)是由一系列值(可以是字符串或数字等等)组成的序列,值与值之间由逗号隔开,整个列表被方括号所包括。

>>> animals = 'dog, cat rabbit. bird, wolf'
>>> animals.split(',')
['dog', ' cat rabbit. bird', ' wolf']

上面例子中,字符串名为 animals,传入的参数为分隔符 ','。字符串将按','来进行分割。如果不指定分隔符,那么 split() 将默认使用空白字符。

>>> animals.split()
['dog,', 'cat', 'rabbit.', 'bird,', 'wolf']

使用join()合并

join() 函数与 split() 函数正好相反:它将包含若干子串的列表分解,并将这些子串合成一个完整的大的字符串。首先指定粘合用的字符串,然后再指定需要合并的列表:string.join(list)。下面的例子将列表中的名字通过逗号及空格粘合在一起:

>>> animals_list = ['dog', 'cat', 'panda']
>>> animals = ', '.join(animals_list)
>>> animals
'dog, cat, panda'
>>> print(animals)
dog, cat, panda

使用replace()替换

使用 replace() 函数可以进行简单的子串替换。你需要传入的参数包括:需要被替换的子串,用于替换的新子串,以及需要替换多少处:

>>> animals = 'cat, cat, dog, dog, duck, rabbit, bird'
>>> animals.replace('cat', 'dog')
'dog, dog, dog, dog, duck, rabbit, bird'

只允许替换一个:

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

推荐阅读更多精彩内容