<! After throwing away the vernier caliper, use PY to splice the code –>

The contents of strings in PY are executed using exec() or eval() when PY code is executed. (Isn’t this a lot like trading with yourself? 😏)

  • The former can execute normal code, but there is no return, so you should execute one.PYThe script.
  • The latter can have a return, but only a single statement. Well, one statement. πŸ™ƒ

The good: https://github.com/pyecharts/pyecharts especially icon.

'I'll always love SpongeBob SquarePants'

It has an example. I changed it a little bit here and here, and it looked like this:

from pyecharts.charts import Bar from pyecharts import options as opts ( Bar(init_opts=opts.InitOpts(width="680px",height="390px",page_title="HAHAHAHA")).add_xaxis([" shirt ", "shirt "," tie ", "pants ", "Trench coat", "high heels", "socks"]) add_yaxis (" businessmen A ", [55, 114, 27, 101, 125, 27, 105]). Add_yaxis (merchants "B", [57, 134, 137, 129, 145, 60, 49]).set_global_opts(title_opts= opts.titleLeopts (title=" Shangjias.html ")).render(" Shangjias.html ").render(" Shangjias.html ")

Then I had an idea: I wanted to automatically generate this code with a random middle section that could specify the number of merchants.

All right, check as you go! (Look it up because I don’t know how to do PY, which is why I have this… Notes? (Throwing a vernier caliper is a sideshow. Come to come, throw away by the way…) )

differentiateexec ε’Œ eval

In fact, Bash has both of these. However, I will only play with the former to simulate the effect of a function that completes the call before starting the next call, thereby implementing functional tail recursion on Bash. There was a little excitement in PY at first, but the process logic in PY is definitely not the same as in Bash, so I’m going to put that aside for now.

Now, the main task is to play PY without vernier calipers, and play dynamic code with PY, these two items, other “a little” later.

In fact, the analysis is simple, in PY:

  • The former can execute normal code, but there is no return, so you should execute one.PYThe script is not returned.
  • The latter can have a return, but only a single statement. Well, one statement. πŸ™ƒ

Note

It’s actually a very reasonable design. Otherwise, it will be like PowerShell, a function can have more than one return, that is too scary.

A Simple Example:

If you copy the following code into your PY and hit enter, you’ll see what it means:

'{} \ n {}'. The format (1, 2)

If you know what the above means, you know what the following means:

'{}\n{}'.format("'yaya{}rara'",".format(2)")

You can see what the following code means (the return results are the same but it is recommended to define the principle separately using the former format data) :

'({}\n{})'.format("'yaya{}rara'",".format(2)")
'{}\n{}'.format("('yaya{}rara'",".format(2))")

All right, keep your eyes open, we’re going to get started!

Let’s first look at the effect of exec and eval parsing the following string:

Exec (' ({}, n {}). The format (" 'yaya {} rara' ", "format (2)")) # didn't print didn't also did not return an error code (not print and right) Eval (' ({}, n {}). The format (" 'yaya {} rara' ", "format (2)")) # return: 'yaya2rara'

And look at this:

Exec (' {}, n {} '. The format (" 'yaya {} rara' ", "format (2)")) # error eval (' {}, n {} '. The format (" 'yaya {} rara' ", "format (2)")) # error

Because PY does not support more liberal formatting, except in brackets πŸ™ƒ. (This is where I take advantage, as I don’t just use parentheses (), but mostly square brackets [] and lambda.)

Pile number

Here’s a little puzzle: While Java or Scala can write full class names to avoid imports, Py can’t. Of course, there may be other ways I don’t know. But anyway, in that case, I’ll just rename the introduced randomness, just call it randomness!

Import random as random

Note

I might want to make it very clear that the following code executes only if the import has already been executed. In fact, I don’t like this design: I think it’s better for one line of code to have all the parts in it, rather than just being part of the necessary work. If it’s just one part, where are you going to get the kids to find the other part? The children will be sad 🀒…

Let’s start with a random list:

RandInt (222,333) for I in range(12)]

You can do it a few times and see what it looks like. Why did I let you see it? Because you’ll never see it again…

Before we get to it, let me just add a little bit about lambda. Not hard, just execute the following code for comparison:

1+2 # return: 3 (lambda x,y: x+y)(1,2) # return: 3 1+1 # return: 2 (lambda x: x+x)(1) # return: 2 [e+7 for e in range(4)] # Lambda x: [e+7 for e in range(x)] [7, 8, 9, 10] ['ahaha {} jijijijijijiji '. Format (e) for e in range(4)] # (lambda x: ['ahaha {} jijijijijiji'. Format (e) for e in range(x)])

Now, someone might say, “Well, this lambda is just an unnecessary lambda,” and you don’t know, but if you have to write one line of code, it’s not going to be assigned, but you have to use a random number twice, what do you do?

Anyway, we’ll come up with that in a second. πŸ™ƒ

And we’ve already seen where we need lambda, where we want to extract the written value as a variable.

Lambda CNT: [random.randint (222,333) for I in range(CNT)])(7)

So you define a function, call it immediately, and return a list of seven random numbers. The random numbers are ints between 222 and 333.

In addition, the definition of a lambda function is itself equivalent to a written value, except that it is not an int or any other type in general. Anyway, it will be returned as a numeric value. Thus, we can have the following definition:

Lambda CNT: (lambda low,high: ([random. RandInt (low,high) for I in range(CNT)]))

Call:

(lambda CNT: (lambda low,high: ([random. RandInt (low,high) for I in range(CNT)]))) (7) (222,333)

There are actually two calls:

  • The argument list for the first call is(7), one was returnedcontentHere are the values:Lambda low,high: ([random. RandInt (low,high) for I in range(7)])
  • And then it’s followed by a list of arguments(222333)., is called again, and this call is the same asperform RandInt (222,333) for I in range(7)].

    (In fact,perform Lambda what: what what The commandtheReturns the resultIs acontentforLambda what: what what ηš„ To determine the value).

Note

In fact, the idea of passing functions around as values is fairly straightforward to write in Lisp languages. I’m just playing with PY in this article, so I’m not going to cover Lisp’s S-expression code. You can look up Scheme syntax and lambda writing for yourself.

The result is a list of seven random numbers. The random numbers are ints (integers) between 222 and 333.

Well, I’d like to make a few of these lists now!

So, suppose we have a list like this:

[(merchants' 1 ', (200300)), (merchants' 2 ', (50600)), (merchants' 3 ', (80100))]

All you need to do is turn the right-hand side into an argument list and call the previous function, and then match the result with the merchant X in front…

It’s not enough! I also want each parameter to be different! I don’t want to do it myself, I just want to use random numbers!

OK, so make a list that you can specify a number of.

We need to pass random arguments to this function randInt (x,y), and make sure that the first one is less than the second one.

So the way I think about it is, I pick the first random value, and then I add a random increment to the second one.

Now you have an idea, let’s start.

First, make a tuple like the one after ‘merchant X’ and randomly:

Random.randint (40,300), random.randint (40,300) + random.randint (10,600))

Wait a minute! Go to hell! It’s entirely possible to make the second number even smaller! Because two random.randInt (40,300) may not have the same value !!!!

How to do? I no longer allow myself to assign values to variables! How to do!

lambda: Don’t worry, young man! Think about this wonderful structure:
(lambda a (a a))(This is the Scheme version, but the Python equivalent would look like this:
(lambda a: a(a)). How’s that? Is Scheme better? 😢) (Also this structure comes from
Y combinator).


It’s actually easier to give an example like this:
(lambda x: x+x)I used it twice! Same number !!!! Unbelief can verify:
Lambda x: (x,x+x))

Anyway, now we have an idea for what we need above:

Lambda rndlow, add: (rndlow, rndlow + add)) (Random.randint (40,300), Random.randint (10,600))

Lambda rndlow = lambda rndlow = lambda rndlow = lambda rndlow = lambda rndlow = lambda rndlow; RandInt (40,300), RandInt (10,600)), where the second term must be the sum of the first and the third term, every time.

Now, one of these things, we’ve got it. Now, we need a list, and in the list, we need several of these things.

What about a list of specified lengths? Look:

[elem*2 for elem in range(12)] ['heihei {} miaomiao'. Format (elem) for elem in range(12)] [RandInt (40,300) for elem in RandInt (40,300), RandInt (10,600)) for elem in range(12) The first value is a random number between 40 and 300, and the second value is a random number between 10 and 600. (The two values are of course not related to each other because logically they are independently random.)

The last two lines don’t actually use elem at the end, the only information passed on is that there are several elem.

In fact the
[new set single element form for by element in by element source set]At the beginning, I was very confused, do not understand why it is such a meaning of each part, because I always go to
forThink about the form of the cycle. When I learned about Erlang, I saw that the list constructor reads like this:
[new collection form of a single element | | based on element < - on source element collection]I immediately understood where PY’s design came from.

OK, I want a binary tuple, but the second one must be bigger than the first one:

[(lambda rndlow,add: (rndlow,rndlow+add)) (random.randInt (40,300), random.randInt (10,600))) for will_not_use in range(13)]

Here, 13.

Let me format it. It’s already very long.

[ (lambda rndlow,add: RandInt (40, 300), RandInt (10, 600)) for will_not_use in range(13)]

Found no? Although we are playing PY but here is formatted free !!!!

(This is just to borrow PY’s character: the contiguous whitespace in parentheses is considered a — of course, this is my personal summary and does not represent the attitude of the PY committee…)

Note

Here’s my formatting rule:

  • A list or tuple with a definite number of values, aligned above and below parentheses, indented one line at a time.
  • List generator, square brackets followed by some space followed by the first item, and thenforThe expression starts on another line and indents it once.
  • lambdaExpressions, of course, are called with parentheses. The header can be either as close as possible to the leading parenthesis, or it can be a line break. In the case of a line break, it is indented two levels further back relative to the level of the leading parenthesis, and the corresponding closing parenthesis is indented in the same wayAnd you should only start another line at that point, unless you can align it up and down; The return value section can be defined on a different line. If it is defined on a different line, it must be relativelambdaIndent back one more time.
  • In addition to the parcellambdaAll parentheses that are defined, except when the content starts on another line, should make sure that the parentheses are either horizontal or vertical. If a new formatting rule is added, it will be done to ensure this rule, or to better ensure this rule.
  • lambdaWhen the definition is called, it is a good idea to make sure that there is some space between the closing parentheses of the package definition and the argument list for good look; But to make it easier for you to debug, it’s best not to go to the next line, just use space spacing.
  • If the contents of the argument list are wrapped separately and indented once back, the closing parentheses can be aligned vertically with the commas above, rather than with the corresponding leading parentheses. This should be the only place where incorrect parentheses are allowed. It is also possible to follow this principle: when you see a misaligned parenthesis, you know it is preceded by an argument list.) (Also, try not to fold the argument list. This is toA pair of parentheses are aligned vertically or horizontally“.)
  • lambdaDefinitions can be assigned without being wrapped in parentheses. If wrapped, follow the rules of the parameter list, i.e. one layer back. Because you can’t open a new line of parentheses…
  • Spaces should be overlaid in order of hierarchy when the closing parentheses of multiple argument lists end in a row.
  • For commas, each comma in the argument list is preceded by a space, and each comma in the tuple is preceded by a space, just like the operator. When called, the argument list must have a space after the comma. Anything else is optional. If we’re going to break a line, we’re going to have a comma with a space before it, and we’re going to have parentheses to distinguish it from the argument list.

Now you can easily make the result look more like the list above:

[(' business {}'.format(I +1), lambda rndlow,add: RandInt (40, 300), RandInt (10, 600))) for I in range(13)]

It’s easy to see when you change the format: just a pair of parentheses before the for (to create a tuple) and a string value at the [0] position. And of course this value here uses the contents of I from range(13).

I would like to specify the number 13 by myself:

(lambda CNT: [(' merchant {}'. Format (I +1)), (lambda rndlow,add: RandInt (40, 300), RandInt (10, 600)) for I in range(CNT)]) (13)

Okay, now it returns a list, and one element of the list might look something like this: (‘ merchant 3’, (240, 713)).

Now we want to form a list where each element looks like this (‘ merchant 3’, [420, 285, 495, 539, 269, 296, 293]) :

[ ( sj[0] , (lambda cnt: lambda low,high: RandInt (low, high) for I in range(CNT)]) (7) (sj[1][0], sj[1][1])) for sj in (lambda CNT: [(' business {}'.format(I +1), lambda rndlow,add: RandInt (40, 300), RandInt (10, 600))) for I in range(CNT)])(13)]

Among them:

  • The first one[This is followed by the calculation logic for each element of the newborn list, based on the variablesfor ε’Œ inBetween the string of things, this thing (in this case is calledsjThe content comes from each item in the subsequent set, which is, of course, based on an input value.
  • And the logic for each element in the newborn list, first of all, it’s a tuple, the first item is the merchant number, and itIn thisJust enough to be based onsj[0]Obtain; You have to have one in the back7Length of a list of random numbers that generate itlambdaThe definition already defined, the required parameters can be based onsj[1]This tuple is fetched, and we’re going to take it separatelysj[1][0] ε’Œ sj[1][1], and write it in the correct position for the incoming argument, and then the function will be able to useParameter designationgenerateA list of random numbers based on parameters and function definitions.
  • So, as long assjIt can always be determined what it is, and the structure of the content and the types of data at various points in the structure are all right, and you get the final result; Fortunately or not, our data source is able to do both. πŸ™ƒ πŸ™ƒ πŸ™ƒ

In this way, we can generate a bunch of data like (‘ merchant 3’, [420, 285, 495, 539, 269, 296, 293]).

What does it do? Its two items fill out a code to spell it?

[ ' .add_yaxis("{}",{})\n'.format(sj_msg[0], sj_msg[1]) for sj_msg in [ ( sj[0] , (lambda cnt: lambda low,high: RandInt (low, high) for I in range(CNT)]) (7) (sj[1][0], sj[1][1])) for sj in (lambda CNT: [(' business {}'.format(I +1), lambda rndlow,add: RandInt (40, 300), RandInt (10, 600))) for I in range(CNT)])(13)]

Of course, that’s not enough. What we need is a string.

Now let’s introduce one more thing: reduce.

However, I’d like to add a word here (in case I need it later) :

You don’t have to introduce it, just use itlambdaI can do a similar thing manually!

Look:

Lambda selff: lambda op, list, res: lambda op, list, res: Res if (list == []) else (selff(selff))(op,list[1::],op(res,list[0]))) selfff(selfff)) ( lambda selff: lambda op, list, res: Res the if (list = = []) else (selff (selff)) (op, list [1: :], op (res, list [0]))) (lambda x, y, x - y,,4,3,2,1 [5], 6) # # returned as the result of: ## This is a non-generic Y combinator used to allow anonymous functions to call themselves (lambda selfff: selfff(selfff)) (lambda selff: lambda selfff(selfff)) lambda op,list,res: If (list == []) else (selff(selff)) op, list[1::], op(res, selff) This is the list of arguments defined at the time of the call: the incoming logic is subtracting the result and subtracting the result, the list is the second item, and the initial value is the third item. Lambda x,y:x-y, [5,4,3,2,1], 6) lambda x,y:x-y, [5,4,3,2,1], 6) lambda x,y:x-y, [5,4,3,2,1], 6) The list I pass in here is written, but what about dynamically generated lists based on variables? ### (Is it a bit of dynamically generated code? Except instead of adding a number, you're adding a string, and you're actually dynamically generating code... # # # πŸ™ƒ πŸ™ƒ πŸ™‚ πŸ™ˆ 🦦 πŸ¦€

The above part is not necessary to master completely, the main is to see the results of your own implementation (you can arbitrarily change the bottom of the parameters to try). In this part, I just want to show that aggregate functions can be defined by lambda calculus alone, and give examples… Even better, if you can use it later. πŸ™ƒ

So let’s use the introduced reduce again.

If you introduce it, it’s an old practice, change the name.

From functools import reduce as a summary

Please pay attention! This introduction is required before the following code can be executed!!

Let’s use this function first to see what happens:

Summary (lambda x, y, x + y, [' add_yaxis (" {}, {}) \ n '. The format (sj_msg [0], sj_msg [1]) for sj_msg in [(sj [0], (lambda CNT: Lambda low,high: [RandInt (low, high) for I in range(CNT)]) (7) (sj[1][0], sj[1][1]))) for sj in (lambda CNT: [(' business {}'.format(I +1), lambda rndlow,add: RandInt (40, 300), RandInt (10, 600))) for I in range(CNT)])(13)])

There’s no escaping of the return value here, but that’s fine, and a more intuitive preview will follow. All you need to do here is make sure that you successfully return an aggregate string.

Better preview options:

x = lambda : Summary (lambda x, y, x + y, [' add_yaxis (" {}, {}) \ n '. The format (sj_msg [0], sj_msg [1]) for sj_msg in [(sj [0], (lambda CNT: Lambda low,high: [RandInt (low, high) for I in range(CNT)]) (7) (sj[1][0], sj[1][1]))) for sj in (lambda CNT: [(' business {}'.format(I +1), lambda rndlow,add: RandInt (40, 300), RandInt (10, 100) 600)) ) for i in range(cnt) ] )(13) ] ] ) print(x()) print(x()) print(x())

Here print(x()) can be executed a few more times. And you’ll see the numbers change, because you’re going to do it all over again every time.

I’m just assigning x here for the convenience of print. After all, Python’s REPL doesn’t logically appear on a single line when pressed, like Zsh or even Bash.

Now, the outermost lambda definition assigned to x is unargued. Do you want to have one? Ah, the number of businesses I want to control here!

So you take the corresponding abstraction from the inside and move it to the outside. The entire definition looks like this:

lambda cnt : Summary (lambda x, y, x + y, [' add_yaxis (" {}, {}) \ n '. The format (sj_msg [0], sj_msg [1]) for sj_msg in [(sj [0], (lambda CNT: lambda low,high: [random. Randint (low, high) for I in range (CNT)]) (7) (sj [1] [0], sj [1] [1])) for sj in [(' {} merchants'. The format (I + 1), RandInt (40, 300), RandInt (10, 600))) for I in range(CNT)]]])

Call:

(lambda cnt : Summary (lambda x, y, x + y, [' add_yaxis (" {}, {}) \ n '. The format (sj_msg [0], sj_msg [1]) for sj_msg in [(sj [0], (lambda CNT: lambda low,high: [random. Randint (low, high) for I in range (CNT)]) (7) (sj [1] [0], sj [1] [1])) for sj in [(' {} merchants'. The format (I + 1), (lambda rndlow,add: RandInt (40, 300), RandInt (10, 600))) for I in range(CNT)]]])) (4)

Look at the result. No problem.

Now it’s time to have fun:

x = lambda cnt : Summary (lambda x, y, x + y, [' add_yaxis (" {}, {}) \ n '. The format (sj_msg [0], sj_msg [1]) for sj_msg in [(sj [0], (lambda CNT: lambda low,high: [random. Randint (low, high) for I in range (CNT)]) (7) (sj [1] [0], sj [1] [1])) for sj in [(' {} merchants'. The format (I + 1), (lambda rndlow,add: RandInt (40, 300), RandInt (10, 100) 600)) ) for i in range(cnt) ] ] ] ) print(x(1)) print(x(2)) print(x(3)) print(x(0))

. It cannot be zero, because the list passed by reduce cannot be empty (because the general logic of reduce is to take the first one as the initial value and then pass the rest of the list and the initial value along with the calculation rule to another aggregate function that defines the initial value).

Just right, try the one I made earlier:

x = lambda cnt : (lambda selfff: selfff(selfff)) ( lambda selff: lambda op,list,res: res if (list == []) else (selff(selff)) ( op, list[1::], op(res, list[0]) ) ) ( lambda x,y:x+y , [ ' .add_yaxis("{}",{})\n'.format(sj_msg[0], sj_msg[1]) for sj_msg in [ ( sj[0] , (lambda cnt: lambda low,high: [random. Randint (low, high) for I in range (CNT)]) (7) (sj [1] [0], sj [1] [1])) for sj in [(' {} merchants'. The format (I + 1), (lambda rndlow,add: RandInt (40, 300), RandInt (10, 600))) for I in range(CNT)]], '' ) print(x(1)) print(x(2)) print(x(3)) print(x(0))

If it’s 0, it returns null. Why? The third parameter I gave is an empty string.

🀣 Le Du Don (hey hey hey hey hey hey hey hey hey)

(It’s not a big deal though, I just failed to implement the encapsulated reduce…)

Now if I change it again, I’ll be able to splice the entire code. I directly enter the results:

xforexec = ( lambda cnt : """ from pyecharts.charts import Bar from pyecharts import options as opts ( Bar(init_opts=opts.InitOpts(width="680px",height="390px",page_title="HAHAHAHA")).add_xaxis([" shirt ", "shirt "," tie ", "pants ", "Trench coat," "high heels," "Socks"]) {}. Set_global_opts (title_opts = opts. TitleOpts (title = "a market sales situation"))). The render (" shangjias. HTML) "" "". The format (# # (- > (a)  (a a)) (lambda selfff: selfff(selfff)) ( ## reduce lambda selff: lambda op,list,res: res if (list == []) else (selff(selff)) ( op, list[1::], op(res, list[0]) ) ) ( ## str adds lambda x,y:x+y , ## str list (need to know val of cnt) [ ' .add_yaxis("{}",{})\n'.format(sj_msg[0], sj_msg[1]) for sj_msg in [ ( sj[0] , (lambda cnt: lambda low,high: [random. Randint (low, high) for I in range (CNT)]) (7) (sj [1] [0], sj [1] [1])) for sj in [(' {} merchants'. The format (I + 1), (lambda rndlow,add: RandInt (40, 300), RandInt (10, 600))) for I in range(CNT)]], ## first of adding '' ) ) ) exec(xforexec(3))

Why not use eval? Because this thing doesn’t return at the end, it generates a file as a side effect.

If you remove the two imports from the string, you could use eval, but it’s not a function, it’s a set of side commands (although only one of them takes effect).

To see this file, you can exit the Python REPL and do this:

python -m http.server 2341

Then visit the node IP:2341/shangjias.html to see the results.

This is an HTTP proxy and is generally used for debugging. It is recommended in production to use Httpd or Nginx to do this.

cheat

There are two imports in this paper:

Import random as random from functools import reduce as summary

Share indicate the source: https://segmentfault.com/a/1190000040317072