Python implementation SLR (1) parser, compiler principle yyds!

osc_ q27elio3 2020-11-14 08:18:55
python implementation slr parser compiler


Python Realization SLR(1) parsers

The night before the experiment class, he had a liver SLR parsers , At that time, I also sent a circle of friends. The parser and I had to leave one at night , From the state of the next day , It should be the two of us who left together ( laugh

  • The writing time is rather short , So some parts of the code are not implemented very well , There are some problems , If you have time in the future, you can mend it , For example, comparing two project specification families is inefficient ,first Set and follow Set to push to ε There may be bug, But in my grammar definition, I deliberately bypass ε, Barely able to use .
  • In order to facilitate code reading , Added a lot of comments after the print statement , Uncomment these print statements and run , Can tell you what the current code is doing .
  • In the process of writing , Try to encapsulate the module , Separate logic from grammatical definitions , The grammar can be easily modified , But there may be a little bit of a problem with too much time . When grammar changes , modify
    getCol function ( This function maps terminator and nonterminal to action and goto The corresponding columns in the table ),initProduction function ( This function defines the grammar production ( Expand grammar ), In this paper, there are 28 A production ),source( Input word sequence ),varset( Nonterminal set ),terminalset( Terminator set )
    

SLR(1) Analysis process

  • Input grammar
  • seek first Set
  • seek follow Set
  • structure LR(0) Project set DFA
  • structure Action and Goto
  • according to Action and Goto Analyze

1. Main data structure definition and basic function :

  Basic function

  1. isVariable Function to determine whether it is a non terminal

  2. isTerminal Function to determine whether it is the end of

  3. transf(production_set, var) function production_set For one LR(0) project , Try to pass through var( Terminator or or nonterminal ) To transfer

  4. isSameStatus(status1, status2) function : Judge status1 and status2 Are they the same LR(0) project

  5. isInPointset(production_set, pointset):# To examine production_set Is it already there point , If there is, put point return ( Generate DFA When used )

 

 

 

data structure

  1. Production uses classes to store ,left and right Respectively list,number‘ Number production
  2. GraphPoint Storage DFA Transfer ,transfer Set for directed edges , An element in a collection is defined by var( Terminator or or nonterminal ), And another one. GraphPoint form

class Production:
def __init__(self, left, right, number):
self.left = left
self.right = right
self.number = number
class GraphPoint:
def __init__(self, begin_production, id):
self.status = begin_production
self.transfer = []
self.id = id
def add_transfer(self, var, graphPoint):
self.transfer.append([var, graphPoint])

2. Grammar defines

1. Analyze the object code :int lexicalanalysis(){  float a; int b; a=1.1; b=2; while(b<100){ b=b+1; a=a+3;}; if(a>5) {b=b-1;} else {b=b+1;}}

2. The parser input is the word sequence output by the lexical analyzer of the target code


source = [[5, "int", " keyword "], [1, "lexicalanalysis", " identifier "], [13, "(", " Left parenthesis "], [14, ")", " Right bracket "], [20, "{", " Left brace "],
[4, "float", " keyword "], [1, "a", " identifier "], [15, ";", " A semicolon "], [5, "int", " keyword "], [1, "b", " identifier "],
[15, ";", " A semicolon "], [1, "a", " identifier "], [12, "=", " Assignment number "], [3, "1.1", " Floating point numbers "], [15, ";", " A semicolon "], [1, "b", " identifier "],
[12, "=", " Assignment number "], [2, "2", " Integers "], [15, ";", " A semicolon "], [8, "while", " keyword "], [13, "(", " Left parenthesis "],
[1, "b", " identifier "], [17, "<", " Less than no. "], [2, "100", " Integers "], [14, ")", " Right bracket "], [20, "{", " Left brace "],
[1, "b", " identifier "], [12, "=", " Assignment number "], [1, "b", " identifier "], [9, "+", " Add Number "], [2, "1", " Integers "], [15, ";", " A semicolon "],
[1, "a", " identifier "], [12, "=", " Assignment number "], [1, "a", " identifier "], [9, "+", " plus "], [2, "3", " Integers "], [15, ";", " A semicolon "],
[21, "}", " Right brace "], [15, ";", " A semicolon "], [6, "if", " keyword "], [13, "(", " Left parenthesis "], [1, "a", " identifier "],
[16, ">", " More than no. "], [2, "5", " Integers "], [14, ")", " Right bracket "], [20, "{", " Left brace "], [1, "b", " identifier "],
[12, "=", " Assignment number "], [1, "b", " identifier "], [10, "-", " minus sign "], [2, "1", " Integers "], [15, ";", " A semicolon "], [21, "}", " Right brace "],
[7, "else", " keyword "], [20, "{", " Left brace "], [1, "b", " identifier "], [12, "=", " Assignment number "], [1, "b", " identifier "],
[9, "+", " plus "], [2, "1", " Integers "], [15, ";", " A semicolon "], [21, "}", " Right brace "], [21, "}", " Right brace "]]

3. Grammar defines : Expand the common grammar 28 A production ,0 In order to ensure that the analyzer has only one accepted state , And the extended production .


def initProduction():
production_list = []
production = Production(["A1"], ["A"], 0)
production_list.append(production)
production = Production(["A"], ["E", "I", "(", ")", "{", "D", "}"], 1)
production_list.append(production)
production = Production(["E"], ["int"], 2)
production_list.append(production)
production = Production(["E"], ["float"], 3)
production_list.append(production)
production = Production(["D"], ["D", ";", "B"], 4)
production_list.append(production)
production = Production(["B"], ["F"], 5)
production_list.append(production)
production = Production(["B"], ["G"], 6)
production_list.append(production)
production = Production(["B"], ["M"], 7)
production_list.append(production)
production = Production(["F"], ["E", "I"], 8)
production_list.append(production)
production = Production(["G"], ["I", "=", "P"], 9)
production_list.append(production)
production = Production(["P"], ["K"], 10)
production_list.append(production)
production = Production(["P"], ["K", "+", "P"], 11)
production_list.append(production)
production = Production(["P"], ["K", "-", "P"], 12)
production_list.append(production)
production = Production(["I"], ["id"], 13)
production_list.append(production)
production = Production(["K"], ["I"], 14)
production_list.append(production)
production = Production(["K"], ["number"], 15)
production_list.append(production)
production = Production(["K"], ["floating"], 16)
production_list.append(production)
production = Production(["M"], ["while", "(", "T", ")", "{", "D", ";", "}"], 18)
production_list.append(production)
production = Production(["N"], ["if", "(", "T", ")", "{", "D",";", "}", "else", "{", "D", ";","}"], 19)
production_list.append(production)
production = Production(["T"], ["K", "L", "K"], 20)
production_list.append(production)
production = Production(["L"], [">"], 21)
production_list.append(production)
production = Production(["L"], ["<"], 22)
production_list.append(production)
production = Production(["L"], [">="], 23)
production_list.append(production)
production = Production(["L"], ["<="], 24)
production_list.append(production)
production = Production(["L"], ["=="], 25)
production_list.append(production)
production = Production(["D"], ["B"], 26)
production_list.append(production)
production = Production(["B"], ["N"], 27)
production_list.append(production)
return production_list

 

3. seek First Set

According to this algorithm, we can solve first Set , The first 8,9 Step can be solved recursively .


def getFirst(production_list, varset, terminalset):
first_dic = {}
# Used to mark first Whether the set has been computed , To prevent double counting from wasting time
done = {}
for var in varset:
first_dic[var] = set()
done[var] = 0
# All terminators first Set is his own
for var in terminalset:
first_dic[var] = {var}
done[var] = 1
# print(" After initialization done",done)
# print(" The initialization of the first_dic",first_dic)
for var in varset:
if done[var] == 0:
# print(" Calculation ",var)
getFirstForVar(var, first_dic, varset, terminalset, done)
# print(" Calculation completed ",var)
# print(" At this time done", done)
# print(" At this time first_dic", first_dic)
else:
pass
return first_dic
def getFirstForVar(var, first_dic, varset, terminalset, done):
# It has been deduced that the direct end
if done[var] == 1:
# print(" I've already deduced that roar ")
return
# Ask for a non terminator first aggregate , The first element on the right is the terminator
for production in production_list:
if var in production.left:
if isTerminal(production.right[0], terminalset):
first_dic[var].add(production.right[0])
# use null For empty characters
if production.right[0] == "null":
# print(" The right side is empty ")
first_dic[var].add("null")
# The first element on the right is a non terminal
for production in production_list:
if var in production.left:
if isVariable(production.right[0], varset):
if var == production.right[0]:
continue
if done[production.right[0]] == 0:
getFirstForVar(production.right[0], first_dic, varset, terminalset, done)
if "null" in first_dic[production.right[0]]:
first_dic[production.right[0]].remove("null")
first_dic[var] = first_dic[var] | first_dic[production.right[0]]
# print(" take ",production.right[0]," Set ",first_dic[production.right[0]]," Incorporated into the ",var," The collection of ",first_dic[var]," in "," obtain ",)
if isVariable(production.right[0], varset) and len(production.right) > 1:
index = 1
count = 1
while isVariable(production.right[index], varset):
index = index + 1
count = count + 1
if index >= len(production.right):
break
i = 0
while i < count:
getFirstForVar(production.right[i], first_dic, varset, terminalset, done)
if "null" in first_dic[production.right[i]]:
getFirstForVar(production.right[i + 1], first_dic, varset, terminalset, done)
first_dic[var] = first_dic[var] | first_dic[production.right[i + 1]]
else:
break
i = i + 1
# Set to... After completion 1
done[var] = 1

4. solve follow Set


By using a nonterminal follow Set , Improve the ability to recognize , yes SLR(1) The core idea of analysis .

Only if the project set contains A→α· , be action[i,x]= rj,x Belong to FOLLOW(A),j For production A→α The number of , In this way, we can solve some of the conflicts of migration and reduction .

ps: There are holes in the code , If there is tricky in grammar ε, For example, several non terminators are pushed to empty continuously , Will produce bug, There is no such thing as time and my grammatical definition ε There is no solution to this problem .

 


def getFollow(varset, terminalset, first_dic, production_list):
follow_dic = {}
done = {}
for var in varset:
follow_dic[var] = set()
done[var] = 0
follow_dic["A1"].add("#")
# for var in terminalset:
# follow_dic[var]=set()
# done[var] = 0
for var in follow_dic:
getFollowForVar(var, varset, terminalset, first_dic, production_list, follow_dic, done)
return follow_dic
def getFollowForVar(var, varset, terminalset, first_dic, production_list, follow_dic, done):
if done[var] == 1:
return
for production in production_list:
if var in production.right:
##index Here, in some extreme cases bug, For example, many times var,index It will only return to the leftmost
if production.right.index(var) != len(production.right) - 1:
follow_dic[var] = first_dic[production.right[production.right.index(var) + 1]] | follow_dic[var]
# It doesn't take into account that there is a non terminal on the right, but it's null The situation of
if production.right[len(production.right) - 1] == var:
if var != production.left[0]:
# print(var, " Absorb ", production.left[0])
getFollowForVar(production.left[0], varset, terminalset, first_dic, production_list, follow_dic,
done)
follow_dic[var] = follow_dic[var] | follow_dic[production.left[0]]
done[var] = 1

5. structure LR(0) Project set DFA

1. First of all, define a CLOSURE function , It will continue to expand the production state in the collection , And finally form a project set closure

def CLOSURE(varset, terminalset, production_set, production_list):

Algorithm :

2. structure DFA. Function definition

def generatingGraph(begin_production_set, varset, terminalset, production_list):

We use 0 To form the initial LR(0) Project set , Generating initial nodes ( The class in the starting data structure ), And put it in a collection , Take one node from the set at a time , To use   every last var Belong to (V | T) Try to transfer , After successful transfer, store the directed edge in the node transfer in , The item set after each transfer determines whether it is a new project set , If it's a new project set , Put the new itemset into the collection , When the set is empty, the algorithm stops .

 


# Generate state transition diagrams
def generatingGraph(begin_production_set, varset, terminalset, production_list):
global id
CLOSURE(varset, terminalset, begin_production_set, production_list)
beginPoint = GraphPoint(begin_production_set, id)
id = id + 1
# print(" From this state !")
# print(beginPoint.id)
# for onepro in beginPoint.status:
# print(onepro.number, " ", onepro.left, "->", onepro.right, " ")
pointset = [beginPoint]
set = varset | terminalset
stack = [beginPoint]
while len(stack) != 0:
currentPoint = stack.pop()
######
# print(" The point is ejected , To transfer !")
# print(currentPoint.id)
# for onepro in currentPoint.status:
# print(onepro.number, " ", onepro.left, "->", onepro.right, " ")
#####
for var in set:
# print(" Try to use ",var," To transfer ")
result = transf(currentPoint.status, var)
if len(result) == 0:
# print(var," Transfer failed !")
continue
else:
# print(var," Transferable !")
# print(" Will use result To transfer !")
# for onepro in result:
# print(onepro.number, " ", onepro.left, "->", onepro.right, " ")
# Find the closure after the transfer
CLOSURE(varset, terminalset, result, production_list)
nextpoint = isInPointset(result, pointset)
if nextpoint is None:
# print(var," Shift to a new state :")
# New nodes are pushed into the search stack and point set , Old nodes can't be pushed in
nextpoint = GraphPoint(result, id)
id = id + 1
pointset.append(nextpoint)
stack.append(nextpoint)
# print(nextpoint.id)
# for onepro in nextpoint.status:
# print(onepro.number, " ", onepro.left, "->", onepro.right, " ")
currentPoint.add_transfer(var, nextpoint)
# print(" Generate a new state ")
# for onepro in result:
# print(onepro.number," ",onepro.left,"->",onepro.right," ")
return pointset
# To form a closure
def CLOSURE(varset, terminalset, production_set=[], production_list=[]):
sizebefore = len(production_list)
sizeafter = -1
# Used to test whether a closure has been formed , Avoid going into an endless loop
flag = 0
for production_in_set in production_set:
if production_in_set.right.index(".") != len(production_in_set.right) - 1:
if isVariable(production_in_set.right[production_in_set.right.index(".") + 1], varset):
flag = 1
if flag == 0:
return
while sizeafter != sizebefore:
for production_in_set in production_set:
# The point on the far right is impossible to shift
if (production_in_set.right.index(".") == len(production_in_set.right) - 1):
continue
i = production_in_set.right.index(".") + 1;
# print(i," length",len(production_in_set.right))
if isTerminal(production_in_set.right[i], terminalset):
continue;
templist = []
for x in production_list:
# print(i,len(production_in_set.right))
if x.left[0] == production_in_set.right[i]:
y = copy.deepcopy(x)
y.right.insert(0, ".")
flag = 0
for one in production_set:
rightflag = 0;
if len(one.right) != len(y.right):
rightflag = 1
else:
for j in range(0, len(y.right)):
if one.right[j] != y.right[j]:
rightflag = 1
if one.left[0] == y.left[0] and rightflag == 0:
flag = 1
if flag == 0:
templist.append(y)
sizebefore = len(production_set)
production_set.extend(templist)
sizeafter = len(production_set)

 

 

6. structure Action and Goto surface

Algorithm :

In the algorithm (1)(2) The idea is similar to flooding control in computer networks , Put the initial nodes into a collection , Take a node from the set , Walk out of a node from all its directed edges , And mark the node as passed , Put all the nodes that have not passed before into the collection , So in the past , Until the set is empty . Some of the statements in the code that print incorrectly are statements that detect whether there is a conflict , Due to the limitation of writing time , Most conflicts can be detected , But a small number of conflicts remain invisible ( Tian hang ).

Algorithm (3)(4) By traversing the production state of the project set, we can judge .


#Cell by Action An element in ,do Show action ,which Representation number , Such as the state of transition or the production sequence number with reduction ,done For whether we have passed through , Similar to flooding control 
class Cell:
def __init__(self):
self.do = -1
self.which = -1
self.done = 0
def initActionAndGoto(pointset, varset, terminalset, begin, follow_dic):
Action = [[Cell() for i in range(len(terminalset))] for j in range(len(pointset))]
Goto = [[-1 for i in range(len(varset))] for j in range(len(pointset))]
for point in pointset:
# Transfer state 
for tran in point.transfer:
if isVariable(tran[0], varset):
if Goto[point.id][getCol(tran[0])] != -1:
print(" error 404")
Goto[point.id][getCol(tran[0])] = tran[1].id
else:
if Action[point.id][getCol(tran[0])].done == 1:
print(" error 403")
Action[point.id][getCol(tran[0])].done = 1
Action[point.id][getCol(tran[0])].do = "S"
Action[point.id][getCol(tran[0])].which = tran[1].id
for production in point.status:
if production.right.index(".") == len(production.right) - 1 and production.left[0] == begin:
if Action[point.id][getCol("#")].done == 1:
print(" error 415")
Action[point.id][getCol("#")].do = "acc"
Action[point.id][getCol("#")].done = 1
if production.right.index(".") == len(production.right) - 1 and production.left[0] != begin:
# stay follow Concentration is the only way to reduce 
for terminal in terminalset:
if terminal in follow_dic[production.left[0]]:
# Collision detection 
if Action[point.id][getCol(terminal)].done == 1:
for xx in point.status:
print(xx.number, " ", xx.left, "->", xx.right)
print("Action surface ", point.id, " That's ok ", getCol(terminal), " Column conflict ")
print(" Original ", Action[point.id][getCol(terminal)].do, Action[point.id][getCol(terminal)].which)
print(" Now? ", "R", production.number)
print(" error 416")
Action[point.id][getCol(terminal)].do = "R"
Action[point.id][getCol(terminal)].done = 1
# Using this production reduction 
Action[point.id][getCol(terminal)].which = production.number
return Action, Goto

 

7. according to Action and Goto Grammatical analysis

Algorithmic thought :

At the beginning, the prefix stack of sentence pattern and the status station are pressed in respectively # and 0 state .

loop :

If the table is si, The first element of the buffer is pushed into the sentence prefix stack , And will i( state ) Push into the state stack

If the table is ri , Then use the following i Expression reduction , The number of pop-up elements is i The number of elements on the right side of expressions , After that, according to the state of the top of the stack and the non terminator from reduction GOTO surface , Find the current status , And put the current state and the non terminal from the specification into the stack respectively .

If the table is error!, Congratulations on the mistake , Look for bug Well ( It is also possible that your input does not conform to the current grammar , Grammar conflicts can also lead to this situation ).

If the table is acc, Congratulations on your success .


# SLR Analysis of start 
def SLR(Action, Goto, source, production_list):
source.append([0, "#", " Terminator "])
statusstack = [0]
sentence_stack = ["#"]
print(source)
while 1:
print("*****************************************")
print(" Buffer remaining elements ", source)
terminal = source.pop(0)
print(" State stack ", statusstack)
print(" Sentence pattern stack ", sentence_stack)
# Move in 
if Action[statusstack[len(statusstack) - 1]][terminal[0]].do == "S":
print(" action : Move in operation , Read from buffer ",terminal[1]," Elements are moved in , And according to Action Push the ",Action[statusstack[len(statusstack) - 1]][terminal[0]].which," state ")
statusstack.append(Action[statusstack[len(statusstack) - 1]][terminal[0]].which)
sentence_stack.append(terminal[1])
elif Action[statusstack[len(statusstack) - 1]][terminal[0]].do == "R":
# reduction 
# Record reduction production 
r_production = 0
for production in production_list:
if production.number == Action[statusstack[len(statusstack) - 1]][terminal[0]].which:
r_production = production
for i in range(len(r_production.right)):
statusstack.pop()
sentence_stack.pop()
statusstack.append(Goto[statusstack[len(statusstack) - 1]][getCol(r_production.left[0])])
print(" action : Reduction operation , according to Action The table uses ",r_production.number," Production reduction ")
sentence_stack.append(r_production.left[0])
source.insert(0, terminal)
elif Action[statusstack[len(statusstack) - 1]][terminal[0]].do == "acc":
print("!!!!!!!!!! Semantic analysis complete !!!!!!!!!!!!!!")
break;
else:
print("error 462!");

8. Run and test


source = [[5, "int", " keyword "], [1, "lexicalanalysis", " identifier "], [13, "(", " Left parenthesis "], [14, ")", " Right bracket "], [20, "{", " Left brace "],
[4, "float", " keyword "], [1, "a", " identifier "], [15, ";", " A semicolon "], [5, "int", " keyword "], [1, "b", " identifier "],
[15, ";", " A semicolon "], [1, "a", " identifier "], [12, "=", " Assignment number "], [3, "1.1", " Floating point numbers "], [15, ";", " A semicolon "], [1, "b", " identifier "],
[12, "=", " Assignment number "], [2, "2", " Integers "], [15, ";", " A semicolon "], [8, "while", " keyword "], [13, "(", " Left parenthesis "],
[1, "b", " identifier "], [17, "<", " Less than no. "], [2, "100", " Integers "], [14, ")", " Right bracket "], [20, "{", " Left brace "],
[1, "b", " identifier "], [12, "=", " Assignment number "], [1, "b", " identifier "], [9, "+", " Add Number "], [2, "1", " Integers "], [15, ";", " A semicolon "],
[1, "a", " identifier "], [12, "=", " Assignment number "], [1, "a", " identifier "], [9, "+", " plus "], [2, "3", " Integers "], [15, ";", " A semicolon "],
[21, "}", " Right brace "], [15, ";", " A semicolon "], [6, "if", " keyword "], [13, "(", " Left parenthesis "], [1, "a", " identifier "],
[16, ">", " More than no. "], [2, "5", " Integers "], [14, ")", " Right bracket "], [20, "{", " Left brace "], [1, "b", " identifier "],
[12, "=", " Assignment number "], [1, "b", " identifier "], [10, "-", " minus sign "], [2, "1", " Integers "], [15, ";", " A semicolon "], [21, "}", " Right brace "],
[7, "else", " keyword "], [20, "{", " Left brace "], [1, "b", " identifier "], [12, "=", " Assignment number "], [1, "b", " identifier "],
[9, "+", " plus "], [2, "1", " Integers "], [15, ";", " A semicolon "], [21, "}", " Right brace "], [21, "}", " Right brace "]]
id = 0
varset = {"A1", "A", "E", "I", "D", "F", "G", "M", "P", "K", "T", "L", "B","N"}
terminalset = {"(", ")", "{", "}", ";", "int", "float", "number", "floating", "while", "if", "else", ">", "<", ">=",
"<=", "==", "=", "#", "+", "-", "id"}
production_list = initProduction()
first_dic = getFirst(production_list, varset, terminalset)
# for x in first_dic:
# print(x," : ",first_dic[x])
follow_dic = getFollow(varset, terminalset, first_dic, production_list)
# print("follow:")
# for x in follow_dic:
# print(x, ":", follow_dic[x])
production = Production(["A1"], [".", "A"], 0)
production_set = [production]
# for x in production_set:
# print(x.number," ",x.left,"->",x.right," ")
pointset = generatingGraph(production_set, varset, terminalset, production_list)
begin = "A1"
Action, Goto = initActionAndGoto(pointset, varset, terminalset, begin, follow_dic)
print("**********************GOTO***********************************")
for i in range(len(Goto)):
print(i, end=" ")
for j in range(len(Goto[i])):
print("%3d" % Goto[i][j], end=" ")
print("")
print("**********************Action***********************************")
for i in range(len(Action)):
print("%2d" % i, end=": ")
for j in range(len(Action[i])):
if (Action[i][j].done == 0):
print("error!", end=" ")
else:
print("%3s" % Action[i][j].do, "%2d" % Action[i][j].which, end=" ")
print("")
SLR(Action, Goto, source, production_list)

 

result :

GOTO surface ( Local ):(60*14)

Action surface ( Local ):60*22

The protocol process ( Local ): common 142 Time

Start :

 

 

end :

 

The complete code compilation principle will be put in the blog

2020.11.12

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

版权声明
本文为[osc_ q27elio3]所创,转载请带上原文链接,感谢

  1. 利用Python爬虫获取招聘网站职位信息
  2. Using Python crawler to obtain job information of recruitment website
  3. Several highly rated Python libraries arrow, jsonpath, psutil and tenacity are recommended
  4. Python装饰器
  5. Python实现LDAP认证
  6. Python decorator
  7. Implementing LDAP authentication with Python
  8. Vscode configures Python development environment!
  9. In Python, how dare you say you can't log module? ️
  10. 我收藏的有关Python的电子书和资料
  11. python 中 lambda的一些tips
  12. python中字典的一些tips
  13. python 用生成器生成斐波那契数列
  14. python脚本转pyc踩了个坑。。。
  15. My collection of e-books and materials about Python
  16. Some tips of lambda in Python
  17. Some tips of dictionary in Python
  18. Using Python generator to generate Fibonacci sequence
  19. The conversion of Python script to PyC stepped on a pit...
  20. Python游戏开发,pygame模块,Python实现扫雷小游戏
  21. Python game development, pyGame module, python implementation of minesweeping games
  22. Python实用工具,email模块,Python实现邮件远程控制自己电脑
  23. Python utility, email module, python realizes mail remote control of its own computer
  24. 毫无头绪的自学Python,你可能连门槛都摸不到!【最佳学习路线】
  25. Python读取二进制文件代码方法解析
  26. Python字典的实现原理
  27. Without a clue, you may not even touch the threshold【 Best learning route]
  28. Parsing method of Python reading binary file code
  29. Implementation principle of Python dictionary
  30. You must know the function of pandas to parse JSON data - JSON_ normalize()
  31. Python实用案例,私人定制,Python自动化生成爱豆专属2021日历
  32. Python practical case, private customization, python automatic generation of Adu exclusive 2021 calendar
  33. 《Python实例》震惊了,用Python这么简单实现了聊天系统的脏话,广告检测
  34. "Python instance" was shocked and realized the dirty words and advertisement detection of the chat system in Python
  35. Convolutional neural network processing sequence for Python deep learning
  36. Python data structure and algorithm (1) -- enum type enum
  37. 超全大厂算法岗百问百答(推荐系统/机器学习/深度学习/C++/Spark/python)
  38. 【Python进阶】你真的明白NumPy中的ndarray吗?
  39. All questions and answers for algorithm posts of super large factories (recommended system / machine learning / deep learning / C + + / spark / Python)
  40. [advanced Python] do you really understand ndarray in numpy?
  41. 【Python进阶】Python进阶专栏栏主自述:不忘初心,砥砺前行
  42. [advanced Python] Python advanced column main readme: never forget the original intention and forge ahead
  43. python垃圾回收和缓存管理
  44. java调用Python程序
  45. java调用Python程序
  46. Python常用函数有哪些?Python基础入门课程
  47. Python garbage collection and cache management
  48. Java calling Python program
  49. Java calling Python program
  50. What functions are commonly used in Python? Introduction to Python Basics
  51. Python basic knowledge
  52. Anaconda5.2 安装 Python 库(MySQLdb)的方法
  53. Python实现对脑电数据情绪分析
  54. Anaconda 5.2 method of installing Python Library (mysqldb)
  55. Python implements emotion analysis of EEG data
  56. Master some advanced usage of Python in 30 seconds, which makes others envy it
  57. python爬取百度图片并对图片做一系列处理
  58. Python crawls Baidu pictures and does a series of processing on them
  59. python链接mysql数据库
  60. Python link MySQL database