编程概述
编程大约涉及程序数据、程序结构、程序(元素)组织、程序输入输出(I/0)等等
一、程序数据(数据结构 / 对象)
1. 值(变量)
变量指向值,对应原始的数据对象,操作变量(数据)是编程的强大之处
2. 类型
值的类型与编程要采用的方法(操作方法)密切相关
3. 数据结构
数据结构是对数据的抽象,合适的数据结构能有效控制研究系统的复杂程度,有效解决问题。Python的数据结构有序列(如字符串、列表、字典)、集合,也可以自定义数据结构。
二、程序结构(布尔操作 / 控制流)
顺序结构、选择结构、循环结构,这3种结构中的一种或多种形成了程序结构
1. 布尔操作符、比较操作符
标准值False和None、各种类型(包括浮点数、复数等)的数值0、空序列(如空字符串、空元组和空列表)以及空映射(如空字典)都被视为假,而其他各种值都被视为真,包括特殊值True。
1.1 布尔操作符
运算符 | 逻辑表达式 | 描述 | 实例 |
---|---|---|---|
and | x and y | 布尔"与" - 如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值。 | (a and b) 返回 20。 |
or | x or y | 布尔"或" - 如果 x 是非 0,它返回 x 的值,否则它返回 y 的计算值。 | (a or b) 返回 10。 |
not | not x | 布尔"非" - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。 | not(a and b) 返回 False |
1.2 比较操作符
运算符 | 描述 | 实例 |
---|---|---|
== | 等于 - 比较对象是否相等 | (a == b) 返回 False。 |
!= | 不等于 - 比较两个对象是否不相等 | (a != b) 返回 true. |
<> | 不等于 - 比较两个对象是否不相等。python3 已废弃。 | (a <> b) 返回 true。这个运算符类似 != 。 |
> | 大于 - 返回x是否大于y | (a > b) 返回 False。 |
< | 小于 - 返回x是否小于y。所有比较运算符返回1表示真,返回0表示假。这分别与特殊的变量True和False等价。 | (a < b) 返回 true。 |
>= | 大于等于 - 返回x是否大于等于y。 | (a >= b) 返回 False。 |
<= | 小于等于 - 返回x是否小于等于y。 | (a <= b) 返回 true。 |
2.控制流
2.1. 顺序结构
简单的指令,依次执行程序语句,每条语句只执行一次。无条件判断和循环重复语句。
def count(iterable): count = sum(iterable) return count
2.2. 选择(判断)结构
包括 if 语句、else语句、elif语句。
# if.py while True: number = 888 guess = int(input('Enter an integer : ')) if guess == number: print('Congratulations, you guessed it.') break elif guess < number: print('No, it is a little higher than that') else: print('No, it is a little lower than that')
2.3 循环结构
包括 while语句、for语句、continue语句、break语句
# 用户名密码验证 while 1: name = '张三' word = '123456' count = 0 user = input('Enter correct user name : ') if user != name: print('forget user name') continue while count < 3: password = input('Enter the password(you have 3 chances):') if password != word: print('Wrong password, please find it back') count+=1 elif password == word: print('Login successful') break break
控制流习题
1. 布尔数据类型的两个值是什么?如何拼写? True,Flase 2. 3 个布尔操作符是什么? and;or;not 3.写出每个布尔操作符的真值表(也就是操作数的每种可能组合,以及操作的结果)。 and 操作符的真值表 表达式 求值为 True and True True True and False False False and True False False and False False or 操作符的真值表 表达式 求值为 True or True True True or False True False or True True False or False False not 操作符的真值表 表达式 求值为 not True False not False True 4.以下表达式求值的结果是什么? (5 > 4) and (3 == 5) Flase not (5 > 4) True (5 > 4) or (3 == 5) True not ((5 > 4) or (3 == 5)) Flase (True and True) and (True == False) Flase (not False) or (not True) True 5. 6 个比较操作符是什么? 操作符 含义 == 等于 != 不等于 < 小于 > 大于 <= 小于等于 >= 大于等于 6.等于操作符和赋值操作符的区别是什么? 等于操作符:意思是相等,值相等,但可能不是同一对象,即不相同,但相同一定相等; 赋值操作符:意指赋值,将值赋给变量 7.解释什么是条件,可以在哪里使用条件。 控制流语句的开始部分是条件,条件的求值是一个布尔值,True 或 False。 控制流语句根据条件的 True 或 False 来决定做什么。 几乎所有的控制流语句都使用条件。 8.识别这段代码中的 3 个语句块: spam = 0 if spam == 10: print('eggs') #语句块1 if spam > 5: print('bacon') # 语句块2 else: print('ham') # 语句块3 print('spam') print('spam') 9.编写代码,如果变量 spam 中存放 1,就打印 Hello,如果变量中存放 2,就打印 Howdy,如果变量中存放其他值,就打印 Greetings! def if_fun(): spam=int(input('Enter a number')) if spam ==1: # 要用相等号不能用赋值号,输入值不是一个对象 print('Hello') elif spam == 2: print('Howdy') else: print('Greetings!') if_fun() 10. 如果程序陷在一个无限循环中, 你可以按什么键? control + c 11. break 和 continue 之间的区别是什么? break:终止while循环; continue:跳回到循环开始处,重新对循环条件求值 12. 在 for 循环中, range(10)、 range(0, 10)和 range(0, 10, 1)之间的区别是什么? 无区别,第一个省略了省略了起始默认值,第二个设定的值和默认值相同,第三个设定的步长与默认值相同 13.编写一小段程序,利用 for 循环,打印出从 1 到 10 的数字。然后利用 while 循环,编写一个等价的程序,打印出从 1 到 10 的数字。 for i in range(1,11): print(i) i=1 while i < 11: print(i) i+=1 14. 如果在名为 spam 的模块中, 有一个名为 bacon()的函数,那么在导入 spam模块后, 如何调用它? spam.bacon() 附加题:在因特网上查找 round()和 abs()函数,弄清楚它们的作用。在交互式环境中尝试使用它们。 >>> abs(-1) # 求绝对值 1 >>> round(0.5) # 浮点数四舍五入不超过5不入 0 >>> round(0.6) # 四舍五入 1 >>> round(2.55) 3 >>> round(2.5) 2 >>> round(2.5555555, 2) # 指定保留位数 2.56
三、程序元素组织(函数 / 类)
1. 函数(面向过程编程)
1.1 程序的栈堆图
# 栈堆图.py def print_twice ( bruce ): print ( bruce ) print ( bruce ) def cat_twice (part1 , part2 ): cat = part1 + part2 print_twice (cat) line1 = 'Bing tiddle' line2 = 'tiddle bang .' cat_twice (line1 , line2 )
1. 每个函数用一个栈帧 (frame) 表示。一个栈帧就是一个线框,函数名在旁边,形参以及 函数内部的变量则在里面。前面例子的堆栈图如图 3.1所示。 2. 这些线框排列成栈的形式,说明了哪个函数调用了哪个函数等信息。在此例中,print_twice 被 cat_twice 调用,cat_twice 又被 __main__ 调用,__main__ 是一个表示最上层栈帧的特殊名 字。当你在所有函数之外创建一个变量时,它就属于 __main__。 3. 每个形参都指向其对应实参的值。因此,part1 和 line1 的值相同,part2 和 line2 的值相 同,bruce 和 cat 的值相同。 4. 如果函数调用时发生错误,Python 会打印出错函数的名字以及调用它的函数的名字,以 及调用后面这个函数 的名字,一直追溯到 __main__ 为止。 例如,如果你试图在 print_twice 里面访问 cat ,你将获得一个 NameError : 5. 这个函数列表被称作回溯 (traceback) 。它告诉你发生错误的是哪个程序文件,错误在 哪一行,以及当时在执行哪个函数。它还会显示引起错误的那一行代码。 回溯中的函数顺序,与堆栈图中的函数顺序一致。出错时正在运行的那个函数则位于回 溯信息的底部。 |
1.2 函数习题
1. 为什么在程序中加入函数会有好处? 函数将多次执行的代码放在一起,消除重复,能够使程序更短、 更易读、 更容易更新。函数将程序的基本元素:变量、表达式和语句,组合在一起。(函数减少了重复的代码。这让程序更短,更容易阅读,更容易修改) 2.函数中的代码何时执行:在函数被定义时,还是在函数被调用时? 被调用时执行,没有调用时函数只是一个语句序列 3.什么语句创建一个函数? def 语句 4.一个函数和一次函数调用有什么区别? 函数包含def语句和在def子句中的代码。函数调用让程序执行函数体(def 语句之后的代码块),函数调用求值为该函数的返回值。 5. Python 程序中有多少全局作用域?有多少局部作用域? 只有1个全局作用域,有多个局部作用域 6.当函数调用返回时,局部作用域中的变量发生了什么? 局部变量销毁 7.什么是返回值?返回值可以作为表达式的一部分吗? 函数调用求值的结果称为返回值 8.如果函数没有返回语句,对它调用的返回值是什么? 隐式返回return None 9.如何强制函数中的一个变量指的是全局变量? 使用global语句,在局部作用域用global语句声明变量为全局变量,则赋值发生在全局作用域,在函数体外打印该变量则为局部作用域赋的值 10. None 的数据类型是什么? None 是 NoneType 数据类型的唯一值 11. importimport areallyourpetsnamederic 语句做了什么? 生成一个名为 areallyourpetsnamederic 的模块对象 12.如果在名为 spam 的模块中,有一个名为 bacon()的函数,在引入 spam 后,如何调用它? spam.bacon() 13.如何防止程序在遇到错误时崩溃? 使用try/expect语句捕获异常并恢复 14. try 子句中发生了什么? except 子句中发生了什么? try: 判断子句是否发生错误,except,如果try中发生错误,执行遇到错误要做的事,否则不执行
1.3 函数代码实践
''' 编写一个名为 collatz()的函数,它有一个名为 number 的参数。如果参数是偶数, 那么 collatz()就打印出 number // 2, 并返回该值。如果 number 是奇数, collatz()就打 印并返回 3 * number + 1。 让用户输入一个整数, 并不断对这个数调用 collatz(), 直 到函数返回值1(令人惊奇的是, 这个序列对于任何整数都有效, 利用这个序列, 你迟早会得到 1! 既使数学家也不能确定为什么。 你的程序在研究所谓的“Collatz 序列”,它有时候被称为“最简单的、 不可能的数学问题”)。 在前面的项目中添加 try 和 except 语句,检测用户是否输入了一个非整数的字 符串。正常情况下, int()函数在传入一个非整数字符串时,会产生 ValueError 错误, 比如 int('puppy')。在 except 子句中,向用户输出一条信息,告诉他们必须输入一个 整数。 ''' def collatz(number): if number == 1: return 1 elif number % 2 == 0: numbers = number // 2 print(numbers) collatz(numbers) elif number % 2 == 1: numbers = 3*number + 1 print(numbers) collatz(numbers) try: number = int(input("请输入一个整数->:")) collatz(number) except ValueError: print("please input a integer number")
2. 类(面向对象编程)
2.1. 类和函数的区别
2.1.1 self 参数
类的方法必须有一个额外的第一个参数(变量)名称,但是在调用这个方法的时候你不为这个参数赋值。这个特别的变量指对象本身,按照惯例它的名称是类的方法必须有一个额外的第一个参数(变量)名称,但是在调用这个方法的时候你不为这个参数赋值。这个特别的变量指对象本身,按照惯例它的名称是 self。
2.1.2 __init__ 方法
__init__ 方法在类的一个对象被建立时,马上运行。
class Person: def __init__(self, name): self.name = name def sayHi(self): print('Hello, my name is', self.name) p = Person('Swaroop') p.sayHi()
2.2 类和对象变量
class Robot: '''Represents a robot, with a name.''' #A class variable, counting the number of robots population = 0 def __init__(self,name): '''Initializes the data.''' self.name = name print('(Initialize {0})'.format(self.name)) #When this person is created, the robot # adds to the population Robot.population += 1 def __del__(self): '''I am dying.''' print('{0} is being destroyed!'.format(self.name)) Robot.population -= 1 if Robot.population == 0: print('{0} was the last one.'.format(self.name)) else: print('There are still {0:d} robots working.'.format(Robot.population)) def sayHi(self): '''Greeting by the robot.Yeah, they can do that.''' print('Greetings, my master call me {0}.'.format(self.name)) def howMany(): '''Prints the current population.''' print('We have {0:d} robots.'.format(Robot.population)) howMany = staticmethod(howMany) droid1 = Robot('R2-D2') droid1.sayHi() Robot.howMany() droid2 = Robot('C-3P0') droid2.sayHi() Robot.howMany() print("\nRobots can do some work here.\n") print("Robots have finished their work. So let's destroy them.") del droid1 del droid2 Robot.howMany() ''' # 等价静态方法 @staticmethod def howMany(): ''Prints the current population.''' print('We have {0:d} robots.'.format(Robot.population)) '''
population 属于 Robot 类,因此是一个类变量。 name 变量属于对象(用 self 给其赋值),因此是一个对象变量。因此,我们使用 Robot.population 来引用 population 类变量,而不是用 self.population来引用。
用 self.name 来引用对象变量 name,而不是Robot.name。howMany 实际上是属于类而不是对象的方法。这意味着我们或者可以定义类方法或者可以定义静态方法,这取决于我们是否需要知道我们是那个类的部分。既然我
们不需要这样的信息,就需要将其定义为静态方法。
2.3 类的继承
# 类的继承代码.py class SchoolMember: '''Represent any school member.''' def __init__(self,name,age): self.name = name self.age = age print('(Initialize SchoolMember:{0})'.format(self.name)) def tell(self): '''Tell my details.''' print('Name:"{0}" Age:"{1}"'.format(self.name,self.age),end='') class Teacher(SchoolMember): '''Repressent a teacher.''' def __init__(self,name,age,salary): super().__init__(name,age) # 两种写法,用supper则不加self self.salary = salary print('(Initialized Teacher:{0})'.format(self.name)) def tell(self): SchoolMember.tell(self) print('Salary:"{0:d}"'.format(self.salary)) class Student(SchoolMember): '''Represents a student''' def __init__(self,name,age,marks): SchoolMember.__init__(self,name,age) self.marks = marks print('(Initialized Student:{0})'.format(self.name)) def tell(self): SchoolMember.tell(self) print('Marks:"{0:d}"'.format(self.marks)) t = Teacher('Mrs.Shrividya',30,30000) s = Student('Swaroop',25,75) print() #pirnts a blank line members = [t,s] # 两个类对象的列表 for member in members: member.tell() # work for both Teacher and Students
为了使用继承,我们把基本类的名称作为一个元组跟在定义类时的类名称之后。然后,我们注意到基本类的 __init__ 方法专门使用 self 变量调用,这样我们就可以初始化对象的基本类部分。
这一点十分重要 ——Python 不会自动调用基本类的constructor,你得亲自显式调用它。
在方法调用之前加上类名称前缀,即class.mothed(),然后把 self 变量及其他参数传递给它。注意,在我们使用 SchoolMember 类的 tell 方法的时候,我们把 Teacher 和 Student的实例仅仅作为 SchoolMember 的实例。
另外,在这个例子中,我们调用了子类型的 tell 方法,而不是 SchoolMember 类的 tell 方法。
四、程序输入输出(读写文件/交互)
1. 习题
1.相对路径是相对于什么? 相对于程序的当前工作目录。 2.绝对路径从什么开始? 从根文件夹开始 3. os.getcwd()和 os.chdir()函数做什么事? os.getcwd() 函数返回当前工作目录。 os.chdir() 函数改变当前工作目录,即切换当前工作目录。 4. .和..文件夹是什么? .是当前文件夹。..是父文件夹。 5. 在 C:\bacon\eggs\spam.txt 中, 哪一部分是目录名称, 哪一部分是基本名称? 'C:\bacon\eggs\'是目录名称,'spam.txt'是基本名称。 6.可以传递给 open()函数的 3 种“模式”参数是什么? 向open()函数字传入第二个参数:符串 'r' 对应读模式, 'w' 对应写模式, 'a' 对应添加模式。 7.如果已有的文件以写模式打开,会发生什么? 原有内容将被删除,如果不想删除用,添加模式打开。 8. read()和 readlines()方法之间的区别是什么? read() 方法将文件的全部内容作为一个字符串返回。 readlines() 返回一个字符串列表,其中每个字符串 是文件内容中的一行。 9. shelf 值与什么数据结构相似? shelf 值类似字典值,它有键和值,以及 keys() 和 values() 方法,类似于同名 的字典方法。
2.代码实践
# 疯狂填词.py ''' 创建一个疯狂填词( Mad Libs)程序,它将读入文本文件, 并让用户在该文本 文件中出现 ADJECTIVE、 NOUN、 ADVERB 或 VERB 等单词的地方, 加上他们自 己的文本。例如,一个文本文件可能看起来像这样: The ADJECTIVE panda walked to the NOUN and then VERB. A nearby NOUN was unaffected by these events. 程序将找到这些出现的单词, 并提示用户取代它们。 Enter an adjective: silly Enter a noun: chandelier Enter a verb: screamed Enter a noun: pickup truck 以下的文本文件将被创建: The silly panda walked to the chandelier and then screamed. A nearby pickup truck was unaffected by these events. 结果应该打印到屏幕上, 并保存为一个新的文本文件。 ''' import re filename = '疯狂填词原始文档.txt' with open(filename,'r') as a: words = a.read() wRegex = re.compile(r'\w[A-Z]+') for content in wRegex.findall(words): replaceContent= input('Enter a %s:\n'%content) regex = re.compile(content) words=regex.sub(replaceContent,words,1) print(words) a.close() # nwfile= open(‘疯狂填词原始文档.txt‘,‘w‘) # nwfile.write(words) # nwfile.close()