今天讲编程思维。


  可能这对初次接触编程的人有用——我不是不想切入正题,我只是想强调根本没什么正题,我可能在其他文章里提过这一点。“编程语言就是语法糖”,可能你不知道什么是语法糖,但是知道的人也未必认同我。我不保证你们能听懂……python的教程有很多,但是我对很多都不满意,所以这算是我的尝试吧。


  我们将实现一个【筛选100以内素数】的程序。我不用python语言,而是用伪代码——伪代码没有固定写法,但是自然不是所有东西都叫伪代码。成为伪代码需要两个性质:

  1.  没有歧义。可能别人会觉得有歧义,只要你觉得没有就行。

  2.  可执行。这意味着你必须输入一个动作,而不是“今天天气很好”等等。


  但可执行的不都是机器可以做的。一般地,你可以让机器做:

  • 创建一个变量。变量就像空盒子,你可以往里放一个东西,但只能放一个。最常见的是装一个数,0,12345,-233333,等等。

  • 向变量里放东西。

  • 对数进行数学运算,并把结果放到某个变量

  • 打印字符串;打印一个数。(“打印”仅仅表示显示在屏幕上,这是一般说法)

  • 条件选择。(以后再说)

  • 循环。(以后再说)


  绝大部分你觉得比较“机械”的工作,机器都可以做。虽说我不知道你们对机器有何感觉……


  现在我们试图实现一个筛选100以内素数的程序。你完全可以按着自己的意愿写,比如:

如果1是素数,打印1
如果2是素数,打印2
如果3是素数,打印3
如果4是素数,打印4
如果5是素数,打印5
如果6是素数,打印6
如果7是素数,打印7
如果8是素数,打印8
如果9是素数,打印9
如果10是素数,打印10
如果11是素数,打印11
如果12是素数,打印12
如果13是素数,打印13
如果14是素数,打印14
如果15是素数,打印15
如果16是素数,打印16
如果17是素数,打印17
如果18是素数,打印18
如果19是素数,打印19
如果20是素数,打印20
如果21是素数,打印21
如果22是素数,打印22
如果23是素数,打印23
如果24是素数,打印24
如果25是素数,打印25
如果26是素数,打印26
如果27是素数,打印27
如果28是素数,打印28
如果29是素数,打印29
如果30是素数,打印30
如果31是素数,打印31
如果32是素数,打印32
如果33是素数,打印33
如果34是素数,打印34
如果35是素数,打印35
如果36是素数,打印36
如果37是素数,打印37
如果38是素数,打印38
如果39是素数,打印39
如果40是素数,打印40
如果41是素数,打印41
如果42是素数,打印42
如果43是素数,打印43
如果44是素数,打印44
如果45是素数,打印45
如果46是素数,打印46
如果47是素数,打印47
如果48是素数,打印48
如果49是素数,打印49
如果50是素数,打印50
如果51是素数,打印51
如果52是素数,打印52
如果53是素数,打印53
如果54是素数,打印54
如果55是素数,打印55
如果56是素数,打印56
如果57是素数,打印57
如果58是素数,打印58
如果59是素数,打印59
如果60是素数,打印60
如果61是素数,打印61
如果62是素数,打印62
如果63是素数,打印63
如果64是素数,打印64
如果65是素数,打印65
如果66是素数,打印66
如果67是素数,打印67
如果68是素数,打印68
如果69是素数,打印69
如果70是素数,打印70
如果71是素数,打印71
如果72是素数,打印72
如果73是素数,打印73
如果74是素数,打印74
如果75是素数,打印75
如果76是素数,打印76
如果77是素数,打印77
如果78是素数,打印78
如果79是素数,打印79
如果80是素数,打印80
如果81是素数,打印81
如果82是素数,打印82
如果83是素数,打印83
如果84是素数,打印84
如果85是素数,打印85
如果86是素数,打印86
如果87是素数,打印87
如果88是素数,打印88
如果89是素数,打印89
如果90是素数,打印90
如果91是素数,打印91
如果92是素数,打印92
如果93是素数,打印93
如果94是素数,打印94
如果95是素数,打印95
如果96是素数,打印96
如果97是素数,打印97
如果98是素数,打印98
如果99是素数,打印99
如果100是素数,打印100

  这【是】伪代码,因为既没有歧义,又可以执行。但机器没法执行,因为“是素数”我们理解,机器并不能理解。但是我们可以把“是素数”拆成几个分开的条件,使得机器可以理解较简单的条件。不过在此之前,我们该先考虑一下,这100行是不是太多了?我们可以用上一些小技巧:

新建一个变量A
把1放进A
如果A中的数是素数,打印A中的数
把A中的数增加1
回到第三行

  原本要100行的代码,现在只要5行了——这就是循环的一大用处,显然“回到第三行”导致了一个循环的形成。但是这个代码并不对,因为它会无限循环下去,根本不会结束,“能不断地打印素数”。所以要做一些修改:

新建一个变量A
把1放进A
如果A中的数是素数,打印A中的数
把A中的数增加1
如果A大于100,跳出循环
回到第三行

  因为这里只有一个循环,所以“跳出循环”是伪代码。python是强大的语言,理应可以把这些伪代码改成python语言,可惜世界上有一个诡异的规定(绝大多数语言,C是例外):不许用“回到第三行”这种话。为了弥补,可以这样写:

新建一个变量A
把1放进A
把下面括号里的话重复100遍
(
如果A中的数是素数,打印A中的数
把A中的数增加1
)

  接下来我们处理“是素数”。如果一个数大于3,并且除以所有大于1、比自身小1的数都有余数,那么它是素数。所以以下两段代码功能是一样的:

1:

如果A中的数是素数,打印A中的数

2:(一般地,我们用直接用变量名称呼其中的东西,虽说用盒子的名字称呼里面的东西很奇怪)

新建一个变量B
新建一个变量“这个数还有可能是素数吗”
把2放进B
把字符串“有可能”放进变量“这个数还有可能是素数吗”
把下面括号里的句子一直重复下去
(
如果A除以B没有余数,那么把字符串“不可能”放进变量“这个数还有可能是素数吗”
把B加上1
如果此时B等于A,那么跳出循环
)
如果变量“这个数还有可能是素数吗”中是“有可能”,打印A中的数

  加到一起,就是这样:(同时循环的只有一层,跳出循环仍然没有歧义)

新建一个变量A
把1放进A
把下面括号里的话重复100遍
(
新建一个变量B
新建一个变量“这个数还有可能是素数吗”
把2放进B
把字符串“有可能”放进变量“这个数还有可能是素数吗”
把下面括号里的句子一直重复下去
(
如果A除以B没有余数,那么把字符串“不可能”放进变量“这个数还有可能是素数吗”
把B加上1
如果此时B等于A,那么跳出循环
)
如果变量“这个数还有可能是素数吗”中是“有可能”,打印A中的数
把A中的数增加1
)

  现在我们第一次正式使用python代码:(#号到行末是注释,不会当成语句运行,仅仅为了方便程序员阅读)

a = 1                                               #   新建变量A, 并把1放进A
for i in range(100):                                #   把下面括号里的话重复100遍
                                                    #(
    b = 2                                           #   新建变量B, 并把2放进B
    这个数还有可能是素数吗 = "有可能"                     #   新建变量“这个数还有可能是素数吗”, 并放入字符串“有可能”
    while True:                                     #   把下面括号里的句子一直重复下去
                                                    #(
        if a % b == 0:这个数还有可能是素数吗 = "不可能"   #   如果A除以B没有余数,那么把字符串“不可能”放进变量“这个数还有可能是素数吗”
        b += 1                                      #   把B加上1
        if a == b:  break                           #   如果此时B等于A,那么跳出循环
                                                    #)
    if 这个数还有可能是素数吗 == "有可能":print(a)        #   如果变量“这个数还有可能是素数吗”中是“有可能”,打印A中的数
    a += 1                                          #   把A中的数增加1
                                                    #)

  “把数放进变量”——即“赋值操作”,用的符号是等号。其实这并不符合直觉,并且用久了会产生错觉。代码中出现的双等号表示比较操作,等号只能用于赋值。

  这段代码中,for i in range(100) 意思是新建一个叫 i 的变量,并且使其为0。python中必须在创建时赋值,其实等于在第一次使用时创建。然后括号——python不用括号,而是在需要括号的时候缩进4格,括号结束的时候向前4格,这样就能对齐了——括号中的内容执行一遍,i 加上1,就这么继续下去。

  然而上面的代码并不工作。你会看到光标不停地闪——因为1并不能用上述方法检验是否为素数。但是从3开始就没问题了——大于1、且比自身小1的数得以存在,逻辑也得以运行了。所以我们把第一行改成a=3 。

  然而结果中出现了101……所以我们再改改……但是这些逻辑错误——而不是语法错误,是这门语言之外的东西了。我们在写伪代码的时候就没有考虑周全,并不是我们没有学好这门语言。


  这个小程序非常原始,但是很关乎思维。我们至少能看到3个启示:(并且长久地有效)

  • 用循环取代重复的东西

  • 注意循环如何结束

  • 注意循环能否开始


  而编程思维以外的东西,也就是传统书籍的绝大多数,我决定略过。但是学会了去提问,你就会发现,你确实只要学这么多就够了,授人以鱼不如授人以渔。接下来讲解几个关键词。


函数

  请看代码:

def f(x):
	return 2*x

a = f(7)	
print(a)

  函数就是函数,可以简化数学操作。然而除了数学操作,函数也可以做其他操作,但是受一些限制。如果你要反复计算一个数的2倍(或者2倍+3+2的这个数倍+……这样的复杂函数),def是很好的选择。def应该是define(中文:定义)的缩写。你可以在函数里写print,引用函数之外的变量,以及 不能 修改函数之外的变量,等等。

  想了解更多,百度搜索“python3函数”,一个技巧是,看不懂就先挑看得懂的看。


字符串

  在python中,【半角,也就是英文下的】引号中的内容会被当成字符串。在英文中是没有前引号和后引号之分的,在从前往后读的时候,第一个会被当成前引号,第二个则与前一个匹配,被当做后引号。可以把字符串赋值给一个变量。如果一串英文不在引号里,那么它会被看成一个变量名称。中文引号起不到引号的作用。空格是一个字符,换行符也是一个字符(不妨print("hello\nworld")),但是换行符不能一下子打出来,人们用“\”后跟一个字母表示这些不可见的符号,\n为换行,\\为\自身,\"为双引号(显然引号不能单独打出来)。牺牲一个符号,获得一堆额外的符号还是值得的。python中,单双引号可以成对混用(匹配同种),但我习惯用单引号处理单个字符(单个字符也是字符串)。

  能放进变量里的东西——比如“字符串”,可以百度“python3字符串方法”(又比如“python3复数方法”,但字符串的方法尤其多)。“方法”就是加个点后跟一个函数,是函数的一种。说“方法”而不说“函数”的人,大多是强调这种函数可以用一个“.”来调用之。至于是怎么回事,下一个教程再说(与“类”有关)


列表

l = [1,2,3,4,5]
print(l [0])
print(l [1])
print(l [2])
print(l [3])
print(l [4])

  五个print打印出12345 。a[ i ]表示a中第 i 个元素,但是起始的一个是“第0个元素”。就像有些楼的底层是“第0层”——这一习惯并非没有优点。

  如果把第一行改成 l=1 ,到下一行会出错。因为整数没有“第n个元素”。

  l后括号前一般不用空格,这里是为了看得清楚

  (“python3列表方法”)


元组

t = (1,2,3,4,5)
print(t[0])
print(t[1])
print(t[2])
print(t[3])
print(t[4])

  元组和列表很相似。但是列表可以在被创建后再次赋值,比如可以a[2] = 100 。但试图用于元组时,会报错。元组不可改变——也并非没有优点

  可以用a, b = (1,2) 一下子赋多个值,仅元组可以。

字典

d = {"name" : "Jack", "age" : "7", "hobby" : "nothing"}
print(d["name"])
print(d["age"])
print(d["hobby"])

  你知道会打印出什么。"name" "age" "hobby"(注意有引号,是字符串)都是字典的“键”,"Jack" 7 "hobby"都是“值”,"Jack"是键"name"对应的值,"name" : "Jack"称为一个“键值对”。值可以说任何能放进变量的东西,键必须是不可修改的东西(比如整数,字符串,元组)


else

  百度“python3条件语句”


异常

  百度“python3条件语句”,“python3 assert”(断言)


文件操作

  代码:(自行理解)(r是read,用读取模式打开;w是write,用写入模式打开,将清除原有内容;还可以用a,用追加模式打开,将在最后继续写入。总之不能回改)

with open("演示.txt",'w') as tp:
	tp.write("六个演示文字\n")
	tp.write("十三个演示文字")
	tp.write("二十个演示文字")
	
	
with open("演示.txt",'r') as tp:
	print(tp.read())
	

print("="*20)
print("===============")

with open("演示.txt",'r') as tp:
	print(tp.readline())
	print(tp.readline())


键盘输入

  代码:(回车确认输入)

s = input("输入提示符> ")
print("刚才输入的是:",s)


模块(导入)

  from xxx import * ,相当于把同一文件夹下的xxx.py 文件内容全部粘贴在这里。

  import xxx,类似上一条,但是如果要使用那个文件中的变量a,要写成xxx.a ;用那个文件中的函数,写成xxx.f( )


布尔值

  True和False,和普通变量名看起来没什么大区别(首字母大写而已),但是为python保留字,即不可对其赋值。1 == 1的值为True,1!= 1为False(不等于的意思),1=='a' 的值为False,3 > 2的值为True,字符串和数字可以比较是否相等,比较大小会报错。如果强制对布尔值做加法,True被视为1,False为0 。

  可搜索“布尔代数”


标准库

  库是模块。多数放在环境变量下。

  例如 import os 后可以使用os.system("echo hello"),你知道那是什么; import sys 后可以sys.stdout = open("xxxxxxxxxxxxxxxxxxxxxxx.txt",'w') ,然后接着随便print点东西看看后果

  搜索“python标准库”


IDE

  有些教程一开始就配置IDE,我认为命令行有必要先讲。所谓IDE就是一个豪华些的记事本,另外会给你一个按钮(但是往往不止一个按钮),点一下,就会给命令行发送消息,比如“python xxx.py”。我用的是Geany,感觉还不错。反正我坚决反对新手用VS和eclipse,我到现在也刚刚能看懂罢了(毕竟不用)。网上搜索“geany python”有教程,但是最后一步我放个图(环境变量的用处来了)

搜狗截图18年01月22日1703_1.png

  只有执行一栏有用,因为python几乎不编译。而且好像只能一下子粘贴,不能输入(我电脑的问题?),在记事本里打完整复制吧。


类、面向对象

  下次的内容。