跳转到主要内容

将Python代码转换为JavaScript字符串,只需用@js装饰它!

项目描述

jsbuilder — 将Python代码转换为JavaScript字符串

只需在Python函数上标注@js,然后对其调用str()即可获取该函数的完整工作的JavaScript版本。为什么?因为为什么不呢。

(如果您喜欢这个,请查看htbuild。它是jsbuilder的HTML等价物:为不喜欢单页语言的用户提供的Python HTML字符串构建器。)

安装

只需PIP即可!

pip install jsbuilder

简单示例

from jsbuilder import js

@js
def js_code():

  def sum_and_check_if_42(a, b):
    c = a + b
    if c == 42:
      return True
    else:
      return False

  result = sum_and_check_if_42(10, 30)
  console.log("Is it 42?", result)

现在您只需调用str(js_code)print(js_code)即可查看该代码的JavaScript版本

(注意:下面的代码已格式化以便于阅读)

function sum_and_check_if_42(a, b) {
  var c = (a + b);

  if (c === 42) {
    return true
  } else {
    return false
  }
};

result = sum_and_check_if_42(10, 30);
console.log("Is it 42?", result)

复杂示例

这是直接从D3文档中复制/粘贴的代码,然后转换为Python

from jsbuilder import js

@js
def js_code():
    bleed = 100
    width = 960
    height = 760

    pack = (d3.layout.pack()
            .sort(None)
            .size([width, height + bleed * 2])
            .padding(2))

    svg = (d3.select("body").append("svg")
           .attr("width", width)
           .attr("height", height)
           .append("g")
           .attr("transform", "translate(0," + (-bleed) + ")"))

    def json_read(js, error, json):
        if error:
            raise error

        node = (svg.selectAll(".node")
                .data(pack.nodes(flatten(json)))
                .filter(lambda d: not d.children)
                .enter()
                .append("g")
                .attr("class", "node")
                .attr("transform", lambda d: "translate(" + d.x + "," + d.y + ")"))

        (node.append("circle")
         .attr("r", lambda d: d.r))

        (node.append("text")
         .text(lambda d: d.name)
         .style("font-size", lambda d: Math.min(2 * d.r, (2 * d.r - 8) / getComputedTextLength() * 24) + "px")
         .attr("dy", ".35em"))

    d3.json("README.json", json_read)

    def flatten(root):
        nodes = []

        def recurse(node):
            if node.children:
                node.children.forEach(recurse)
            else:
                nodes.push({"name": node.name, "value": node.size})

        recurse(root)
        return {"children": nodes}

转换后的JS版本是

var bleed = 100;
var width = 960;
var height = 760;

var pack = d3.layout
    .pack()
    .sort(null)
    .size([width, (height + (bleed * 2))])
    .padding(2);

var svg = d3.select("body")
    .append("svg")
    .attr("width", width).attr("height", height)
    .append("g")
    .attr("transform", (("translate(0," + (-bleed)) + ")"));

function json_read(js, error, json) {
    if (error) {
        throw new Error(error)
    } else {
    };
    var node = svg.selectAll(".node")
        .data(pack.nodes(flatten(json)))
        .filter(((d) => ((!d.children))))
        .enter()
            .append("g")
            .attr("class", "node")
            .attr("transform", ((d) => (
                (((("translate(" + d.x) + ",") + d.y) + ")"))));
    node.append("circle")
        .attr("r", ((d) => (d.r)));
    node.append("text")
        .text(((d) => (d.name)))
        .style("font-size", ((d) => (
            (Math.min(
                (2 * d.r),
                ((((2 * d.r) - 8) / getComputedTextLength()) * 24)
            ) + "px"))))
        .attr("dy", ".35em")
};

d3.json("README.json", json_read);

function flatten(root) {
    var nodes = [];

    function recurse(node) {
        if (node.children) {
            node.children.forEach(recurse)
        } else {
            nodes.push({"name": node.name, "value": node.size})
        }
    };

    recurse(root);
    return {"children": nodes}
}

支持

一些Python功能目前尚不支持(如assertasync),而其他一些可能永远不会支持,因为它们在JS中没有明显的对应物(如切片和in运算符)。

完整列表请参见源代码

此外,Python有一些关键字(如from)在JavaScript中不是关键字,因此您不能直接在代码中使用这些关键字,例如变量名和对象成员。如果确实需要,您将不得不寻找解决方案。例如,您必须使用Array['from']()而不是Array.from()

for循环

“for”循环有点棘手!虽然支持,但Python和JS的“for”循环语法差异很大,无法完美转换。相反,Python的“for”循环被映射到JS的“.forEach()”。因此,你可以这样做

for word in ["hello", "hi", "whattup"]:
  console.log(word)

...因为这样转换成

["hello", "hi", "whattup"].forEach((word, _i) => console.log(word))

注意,如果你使用诸如“range()”和“enumerate()”之类的功能,这些在JS中不存在,所以你必须首先定义它们。例如

def range(n):
  return Array['from'](Array(n).keys())

for i in range(10):
  console.log(i)

...这转换成

function range(n) {
    return Array["from"](Array(n).keys())
};

range(10).forEach((i, _i) => {
    console.log(i)
})

相关:你注意到在JS版本的“for”/“forEach”循环中你会免费获得一个“_i”变量吗?在Python版本的JS代码中,你可以自由使用这个变量,因为“enumerate()”不起作用!

变量声明

像这样的Python代码可以正确地转换成JS

# Python
a = 0
a = 10
// JavaScript
var a = 0;
a = 10

稍微复杂一些的情况也可以

# Python
def foo(b):
  a = 0
  a = b = c = 10
// JavaScript
function foo(b) {
  var a = 0;
  a = 10;
  b = 10;
  var c = 10
}

然而,由于Python和JS变量提升的方式不同,在两个世界中,在“if”/“else”块等位置声明的变量处理方式没有不同。特别是,这段Python代码

if x:
  a = 10
else:
  a = 100

变成了这段JS代码

if (x) {
  var a = 10
} else {
  a = 100
}

...这是正确的,但相当奇怪!

如果出于任何原因需要解决这个问题,只需在“if”上方声明变量即可

# Python

a = None

if x:
  a = 10
else:
  a = 100
// JavaScript

var a = null

if (x) {
  a = 10
} else {
  a = 100
}

项目详情


下载文件

下载适用于您的平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分发

jsbuilder-0.1.1.tar.gz (11.1 kB 查看哈希值)

上传时间

由以下提供支持