phpy icon indicating copy to clipboard operation
phpy copied to clipboard

py2php转换错误例子

Open he426100 opened this issue 2 years ago • 1 comments

  1. Parse error: syntax error, unexpected token ")" on line 18
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");
$str_val = "apples";
$num_val = 42;
PyCore::print($num_val . " " . $str_val);
$str_val = "apples";
$num_val = 42;
PyCore::print("str_val=" . $str_val . ", num_val = " . $num_val);
$num_val = 42;
PyCore::print("num_val % 2 = " . $num_val % 2);
$str_val = "apples";
PyCore::print($str_val);
$price_val = 6.12658;
PyCore::print(round($price_val, 2));
$datetime = PyCore::import('datetime')->datetime;
$date_val = $datetime->utcnow();
PyCore::print("date_val=" . );


str_val = 'apples'
num_val = 42

print(f'{num_val} {str_val}') # 42 apples

str_val = 'apples'
num_val = 42

print(f'{str_val=}, {num_val = }') # str_val='apples', num_val = 42

num_val = 42

print(f'{num_val % 2 = }') # num_val % 2 = 0

str_val = 'apples'

print(f'{str_val!r}') # 'apples'

price_val = 6.12658

print(f'{price_val:.2f}') # 6.13

from datetime import datetime;

date_val = datetime.utcnow()

print(f'{date_val=:%Y-%m-%d}') # date_val=2021-07-09

  1. Warning: Undefined variable $timedelta on line 9
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");
$date = PyCore::import('datetime')->date;
$datetime = PyCore::import('datetime')->datetime;
$timedelta = PyCore::import('datetime')->timedelta;

function add_days($n, $d) {
    return $d + $timedelta($n);
}


add_days(5, $date(2020, 10, 25));
add_days(-5, $date(2020, 10, 25));


from datetime import date, datetime, timedelta

def add_days(n, d = datetime.today()):
  return d + timedelta(n)

add_days(5, date(2020, 10, 25)) # date(2020, 10, 30)
add_days(-5, date(2020, 10, 25)) # date(2020, 10, 20)

  1. Parse error: syntax error, unexpected variable "$x", expecting ":" on line 18
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function average_by($lst, $fn) {
    return PyCore::sum(PyCore::map($fn, $lst), 0) / PyCore::len($lst);
}


average_by(new PyList([new PyDict([
    "n" => 4,
]), new PyDict([
    "n" => 2,
]), new PyDict([
    "n" => 8,
]), new PyDict([
    "n" => 6,
])]), return $x->__getitem__("n");

});


def average_by(lst, fn = lambda x: x):
  return sum(map(fn, lst), 0.0) / len(lst)

average_by([{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }], lambda x: x['n'])
# 5.0

  1. Parse error: syntax error, unexpected token "$", expecting variable on line 6
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function bifurcate($lst, $filter) {
    return new PyList([(function($) {
        $___ = [];
        $elts = [];
        foreach($ as [$x, $flag]) {
            $elts[0] = [$x, $flag];
        }
        $___[] = $elts;
        return $___;
    })($), (function($) {
        $___ = [];
        $elts = [];
        foreach($ as [$x, $flag]) {
            $elts[0] = [$x, $flag];
        }
        $___[] = $elts;
        return $___;
    })($)]);
}


bifurcate(new PyList(["beep", "boop", "foo", "bar"]), new PyList([true, true, false, true]));


def bifurcate(lst, filter):
  return [
    [x for x, flag in zip(lst, filter) if flag],
    [x for x, flag in zip(lst, filter) if not flag]
  ]

bifurcate(['beep', 'boop', 'foo', 'bar'], [True, True, False, True])
# [ ['beep', 'boop', 'bar'], ['foo'] ]

  1. Fatal error: Uncaught Error: Call to a member function encode() on string in /home/mrpzx/git/phpy/phpy-examples/30s/python-code/byte-size.php:6
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function byte_size($s) {
    return PyCore::len($s->encode("utf-8"));
}


byte_size("😀");
byte_size("Hello World");


def byte_size(s):
  return len(s.encode('utf-8'))

byte_size('😀') # 4
byte_size('Hello World') # 11

  1. Fatal error: Uncaught Error: Call to a member function title() on string in /home/mrpzx/git/phpy/phpy-examples/30s/python-code/capitalize-every-word.php:6
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function capitalize_every_word($s) {
    return $s->title();
}


capitalize_every_word("hello world!");


def capitalize_every_word(s):
  return s.title()

capitalize_every_word('hello world!') # 'Hello World!'

  1. Fatal error: Uncaught ArgumentCountError: Too few arguments to function capitalize(), 1 passed on line 10
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function capitalize($s, $lower_rest) {
    return PyCore::str("")->join(new PyList([$s->__getitem__(PyCore::slice(null, 1, null))->upper(), $lower_rest ? $s->__getitem__(PyCore::slice(1, null, null))->lower() : $s->__getitem__(PyCore::slice(1, null, null))]));
}


capitalize("fooBar");
capitalize("fooBar", true);


def capitalize(s, lower_rest = False):
  return ''.join([s[:1].upper(), (s[1:].lower() if lower_rest else s[1:])])

capitalize('fooBar') # 'FooBar'
capitalize('fooBar', True) # 'Foobar'

  1. Warning: Undefined variable $tuple on line 6
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function cast_list($val) {
    return PyCore::isinstance($val, [$tuple, $list, $set, $dict]) ? PyCore::list($val) : new PyList([$val]);
}


cast_list("foo");
cast_list(new PyList([1]));
cast_list(["foo", "bar"]);


def cast_list(val):
  return list(val) if isinstance(val, (tuple, list, set, dict)) else [val]

cast_list('foo') # ['foo']
cast_list([1]) # [1]
cast_list(('foo', 'bar')) # ['foo', 'bar']

  1. Parse error: syntax error, unexpected variable "$lst", expecting ":" on line 8
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");
$ceil = PyCore::import('math')->ceil;

function chunk_into_n($lst, $n) {
    $size = $ceil(PyCore::len($lst) / $n);
    return PyCore::list(PyCore::map(return $lst->__getitem__(PyCore::slice($x * $size, $x * $size + $size, null));

    }, PyCore::list(PyCore::range($n))));
}


chunk_into_n(new PyList([1, 2, 3, 4, 5, 6, 7]), 4);


from math import ceil

def chunk_into_n(lst, n):
  size = ceil(len(lst) / n)
  return list(
    map(lambda x: lst[x * size:x * size + size],
    list(range(n)))
  )

chunk_into_n([1, 2, 3, 4, 5, 6, 7], 4) # [[1, 2], [3, 4], [5, 6], [7]]

  1. Parse error: syntax error, unexpected token "!", expecting ":" on line 72
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function difference($a, $b) {
    return (function($a) {
        $___ = [];
        $elts = [];
        foreach($a as $item) {
            $elts[0] = $item;
        }
        $___[] = $elts;
        return $___;
    })($a);
}



function difference($a, $b) {
    return (function($a) {
        $___ = [];
        $elts = [];
        foreach($a as $item) {
            $elts[0] = $item;
        }
        $___[] = $elts;
        return $___;
    })($a);
}



function difference($a, $b) {
    return (function($a) {
        $___ = [];
        $elts = [];
        foreach($a as $item) {
            $elts[0] = $item;
        }
        $___[] = $elts;
        return $___;
    })($a);
}



function make_set($itr) {
    PyCore::print("Making set...");
    return PyCore::set($itr);
}


PyCore::print(difference(new PyList([1, 2, 3]), new PyList([1, 2, 4])));

function difference($a, $b) {
    $_b = PyCore::set($b);
    return (function($a) {
        $___ = [];
        $elts = [];
        foreach($a as $item) {
            $elts[0] = $item;
        }
        $___[] = $elts;
        return $___;
    })($a);
}



function difference($a, $b) {
    $_b = PyCore::set($b);
    return PyCore::list(PyCore::filter(return !$_b->__contains__($item)

    }, $a));
}




def difference(a, b):
  return [item for item in a if item not in b]



def difference(a, b):
  return [item for item in a if item not in set(b)]



def difference(a, b):
  return [item for item in a if item not in make_set(b)]

def make_set(itr):
  print('Making set...')
  return set(itr)

print(difference([1, 2, 3], [1, 2, 4]))
# Making set...
# Making set...
# Making set...
# [3]



def difference(a, b):
  _b = set(b)
  return [item for item in a if item not in _b]



def difference(a, b):
  _b = set(b)
  return list(filter(lambda item: item not in _b, a))

  1. Fatal error: Cannot redeclare compact() on line 6
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function compact($lst) {
    return PyCore::list(PyCore::filter(null, $lst));
}


compact(new PyList([0, 1, false, 2, "", 3, "a", "s", 34]));


def compact(lst):
  return list(filter(None, lst))

compact([0, 1, False, 2, '', 3, 'a', 's', 34]) # [ 1, 2, 3, 'a', 's', 34 ]

  1. Fatal error: Can't use method return value in write context on line 12
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");
$defaultdict = PyCore::import('collections')->defaultdict;
$floor = PyCore::import('math')->floor;

function count_by($lst, $fn) {
    $count = $defaultdict($int);
    $__iter = PyCore::iter(PyCore::map($fn, $lst));
    while($current = PyCore::next($__iter)) {
        $val = $current;
        $countval->__setitem__($val, $__value) += 1;    
    }
    return PyCore::dict($count);
}


count_by(new PyList([6.1, 4.2, 6.3]), $floor);
count_by(new PyList(["one", "two", "three"]), $len);


from collections import defaultdict
from math import floor

def count_by(lst, fn = lambda x: x):
  count = defaultdict(int)
  for val in map(fn, lst):
    count[val] += 1
  return dict(count)

count_by([6.1, 4.2, 6.3], floor) # {6: 2, 4: 1}
count_by(['one', 'two', 'three'], len) # {3: 2, 5: 1}

  1. Fatal error: Uncaught PyError: ('min',) in /home/mrpzx/git/phpy/phpy-examples/30s/python-code/dict-getkey-vs-dictkey.php:14
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");
$a = new PyDict([
    "max" => 200,
]);
$b = new PyDict([
    "min" => 100,
    "max" => 250,
]);
$c = new PyDict([
    "min" => 50,
]);
$a->__getitem__("min") + $b->__getitem__("min") + $c->__getitem__("min");
$a->get("min", 0) + $b->get("min", 0) + $c->get("min", 0);


a = { 'max': 200 }
b = { 'min': 100, 'max': 250 }
c = { 'min': 50 }

a['min'] + b['min'] + c['min'] # throws KeyError
a.get('min', 0) + b.get('min', 0) + c.get('min', 0) # 150

  1. Warning: Undefined variable $int on line 6
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function digitize($n) {
    return PyCore::list(PyCore::map($int, PyCore::str($n)));
}


digitize(123);


def digitize(n):
  return list(map(int, str(n)))

digitize(123) # [1, 2, 3]

  1. Warning: Undefined variable $print on line 14
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function for_each($itr, $fn) {
    $__iter = PyCore::iter($itr);
    while($current = PyCore::next($__iter)) {
        $el = $current;
        $fn($el);    
    }
}


for_each(new PyList([1, 2, 3]), $print);


def for_each(itr, fn):
  for el in itr:
    fn(el)

for_each([1, 2, 3], print) # 1 2 3

  1. Fatal error: Uncaught TypeError: Unsupported operand types: PyList + PyList on line 6
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function have_same_contents($a, $b) {
    $__iter = PyCore::iter(PyCore::set($a + $b));
    while($current = PyCore::next($__iter)) {
        $v = $current;
        if ($a->count($v) != $b->count($v)) {
            return false;
        }
    
    }
    return true;
}


have_same_contents(new PyList([1, 2, 4]), new PyList([2, 4, 1]));


def have_same_contents(a, b):
  for v in set(a + b):
    if a.count(v) != b.count(v):
      return False
  return True

have_same_contents([1, 2, 4], [2, 4, 1]) # True

  1. Error: Unsupported Python Syntax, Line: 3, Type: GeneratorExp
Error: Unsupported Python Syntax, Line: 3, Type: GeneratorExp


def hex_to_rgb(hex):
  return tuple(int(hex[i:i+2], 16) for i in (0, 2, 4))

hex_to_rgb('FFA501') # (255, 165, 1)

  1. Parse error: syntax error, unexpected double-quoted string " ", expecting ":" on line 7
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");
$sub = PyCore::import('re')->sub;

function kebab($s) {
    return PyCore::str("-")->join($sub("(\\s|_|-)+", " ", $sub("[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+", return " " + $mo->group(0)->lower();

    }, $s))->split());
}


kebab("camelCase");
kebab("some text");
kebab("some-mixed_string With spaces_underscores-and-hyphens");
kebab("AllThe-small Things");


from re import sub

def kebab(s):
  return '-'.join(
    sub(r"(\s|_|-)+"," ",
    sub(r"[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+",
    lambda mo: ' ' + mo.group(0).lower(), s)).split())

kebab('camelCase') # 'camel-case'
kebab('some text') # 'some-text'
kebab('some-mixed_string With spaces_underscores-and-hyphens')
# 'some-mixed-string-with-spaces-underscores-and-hyphens'
kebab('AllThe-small Things') # 'all-the-small-things'

  1. Fatal error: Uncaught TypeError: Unsupported operand types: PyObject - int in /home/mrpzx/git/phpy/phpy-examples/30s/python-code/median.php:9
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function median($list) {
    $list->sort();
    $list_length = PyCore::len($list);
    if ($list_length % 2 == 0) {
        return $list->__getitem__(PyCore::int($list_length / 2) - 1) + $list->__getitem__(PyCore::int($list_length / 2)) / 2;
    }

    return PyCore::float($list->__getitem__(PyCore::int($list_length / 2)));
}


median(new PyList([1, 2, 3]));
median(new PyList([1, 2, 3, 4]));


def median(list):
  list.sort()
  list_length = len(list)
  if list_length % 2 == 0:
    return (list[int(list_length / 2) - 1] + list[int(list_length / 2)]) / 2
  return float(list[int(list_length / 2)])

median([1, 2, 3]) # 2.0
median([1, 2, 3, 4]) # 2.5

  1. Fatal error: Cannot redeclare append() (previously declared on line 20
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function append($n, $l) {
    $l->append($n);
    return $l;
}


append(0);
append(1);

function append($n, $l) {
    if ($l == null) {
        $l = new PyList([]);
    }

    $l->append($n);
    return $l;
}


append(0);
append(1);


def append(n, l = []):
  l.append(n)
  return l

append(0) # [0]
append(1) # [0, 1]



def append(n, l = None):
  if l is None:
    l = []
  l.append(n)
  return l

append(0) # [0]
append(1) # [1]

  1. Fatal error: Uncaught TypeError: Unsupported operand types: string * int in /home/mrpzx/git/phpy/phpy-examples/30s/python-code/n-times-string.php:6
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function n_times_string($s, $n) {
    return $s * $n;
}


n_times_string("py", 4);


def n_times_string(s, n):
  return (s * n)

n_times_string('py', 4) #'pypypypy'

  1. Fatal error: Uncaught TypeError: Unsupported operand types: PyObject / PyObject in /home/mrpzx/git/phpy/phpy-examples/30s/python-code/num-to-range.php:6
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function num_to_range($num, $inMin, $inMax, $outMin, $outMax) {
    return $outMin + PyCore::float($num - $inMin) / PyCore::float($inMax - $inMin) * $outMax - $outMin;
}


num_to_range(5, 0, 10, 0, 100);


def num_to_range(num, inMin, inMax, outMin, outMax):
  return outMin + (float(num - inMin) / float(inMax - inMin) * (outMax
                  - outMin))

num_to_range(5, 0, 10, 0, 100) # 50.0

  1. Fatal error: Uncaught Error: Call to a member function getitem() on string in /home/mrpzx/git/phpy/phpy-examples/30s/python-code/reverse.php:6
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function reverse($itr) {
    return $itr->__getitem__(PyCore::slice(null, null, -1));
}


reverse(new PyList([1, 2, 3]));
reverse("snippet");


def reverse(itr):
  return itr[::-1]

reverse([1, 2, 3]) # [3, 2, 1]
reverse('snippet') # 'teppins'

  1. Fatal error: Uncaught PyError: attempt to assign sequence of size 3 to extended slice of size 2 in /home/mrpzx/git/phpy/phpy-examples/30s/python-code/slice-assignment.php:31
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");
$nums = new PyList([1, 2, 3, 4, 5]);
$__value = new PyList([6]);
$nums->__setitem__(PyCore::slice(null, 1, null), $__value);
$__value = new PyList([7, 8]);
$nums->__setitem__(PyCore::slice(1, 3, null), $__value);
$__value = new PyList([9, 0]);
$nums->__setitem__(PyCore::slice(-2, null, null), $__value);
$nums = new PyList([1, 2, 3, 4, 5]);
$__value = new PyList([6, 7]);
$nums->__setitem__(PyCore::slice(1, 4, null), $__value);
$__value = new PyList([8, 9, 0]);
$nums->__setitem__(PyCore::slice(-1, null, null), $__value);
$__value = new PyList([]);
$nums->__setitem__(PyCore::slice(null, 1, null), $__value);
$nums = new PyList([1, 2, 3, 4, 5]);
$__value = new PyList([6, 7]);
$nums->__setitem__(PyCore::slice(2, 2, null), $__value);
$__value = new PyList([8, 9]);
$nums->__setitem__(PyCore::slice(7, null, null), $__value);
$__value = new PyList([0]);
$nums->__setitem__(PyCore::slice(null, 0, null), $__value);
$__value = new PyList([4, 2]);
$nums->__setitem__(PyCore::slice(null, null, null), $__value);
$nums = new PyList([1, 2, 3, 4, 5]);
$__value = new PyList([6, 7]);
$nums->__setitem__(PyCore::slice(2, 5, 2), $__value);
$__value = new PyList([6, 7, 8]);
$nums->__setitem__(PyCore::slice(2, 5, 2), $__value);
$__value = new PyList([9, 0]);
$nums->__setitem__(PyCore::slice(1, null, -1), $__value);


nums = [1, 2, 3, 4, 5]

nums[:1] = [6]        # [6, 2, 3, 4, 5]   (replace elements 0 through 1)
nums[1:3] = [7, 8]    # [6, 7, 8, 4, 5]   (replace elements 1 through 3)
nums[-2:] = [9, 0]    # [6, 7, 8, 9, 0]   (replace the last 2 elements)

nums = [1, 2, 3, 4, 5]

nums[1:4] = [6, 7]    # [1, 6, 7, 5]        (replace 3 elements with 2)
nums[-1:] = [8, 9, 0] # [1, 6, 7, 8, 9, 0]  (replace 1 element with 3)
nums[:1] = []         # [6, 7, 8, 9, 0]     (replace 1 element with 0)

nums = [1, 2, 3, 4, 5]

nums[2:2] = [6, 7]    # [1, 2, 6, 7, 3, 4, 5]   (insert 2 elements)
nums[7:] = [8, 9]     # [1, 2, 6, 7, 3, 4, 5, 8, 9] (append 2 elements)
nums[:0] = [0]        # [0, 1, 2, 6, 7, 3, 4, 5, 8, 9] (prepend 1 element)
nums[:] = [ 4, 2]     # [4, 2]         (replace whole list with a new one)

nums = [1, 2, 3, 4, 5]

nums[2:5:2] = [6, 7]  # [1, 2, 6, 4, 7] (replace every 2nd element, 2 through 5)
nums[2:5:2] = [6, 7, 8] # Throws a ValueError (can't replace 2 elements with 3)
nums[1::-1] = [9, 0]  # [0, 9, 6, 4, 7] (reverse replace, 1 through start)
  1. Fatal error: Uncaught Error: Call to a member function lower() on string in /home/mrpzx/git/phpy/phpy-examples/30s/python-code/slugify.php:7
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");
$re = PyCore::import('re');

function slugify($s) {
    $s = $s->lower()->strip();
    $s = $re->sub("[^\\w\\s-]", "", $s);
    $s = $re->sub("[\\s_-]+", "-", $s);
    $s = $re->sub("^-+|-+$", "", $s);
    return $s;
}


slugify("Hello World!");


import re

def slugify(s):
  s = s.lower().strip()
  s = re.sub(r'[^\w\s-]', '', s)
  s = re.sub(r'[\s_-]+', '-', s)
  s = re.sub(r'^-+|-+$', '', s)
  return s

slugify('Hello World!') # 'hello-world'

  1. Parse error: syntax error, unexpected token "return" on line 6
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function sort_dict_by_value($d, $reverse) {
    return PyCore::dict(PyCore::sorted($d->items(), key: return $x->__getitem__(1);

    }, reverse: $reverse));
}


$d = new PyDict([
    "one" => 1,
    "three" => 3,
    "five" => 5,
    "two" => 2,
    "four" => 4,
]);
sort_dict_by_value($d);
sort_dict_by_value($d, true);


def sort_dict_by_value(d, reverse = False):
  return dict(sorted(d.items(), key = lambda x: x[1], reverse = reverse))

d = {'one': 1, 'three': 3, 'five': 5, 'two': 2, 'four': 4}
sort_dict_by_value(d) # {'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5}
sort_dict_by_value(d, True)
# {'five': 5, 'four': 4, 'three': 3, 'two': 2, 'one': 1}

  1. Fatal error: Uncaught Error: Call to a member function split() on string in /home/mrpzx/git/phpy/phpy-examples/30s/python-code/split-lines.php:6
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function split_lines($s) {
    return $s->split("\n");
}


split_lines("This\nis a\nmultiline\nstring.\n");


def split_lines(s):
  return s.split('\n')

split_lines('This\nis a\nmultiline\nstring.\n')
# ['This', 'is a', 'multiline', 'string.' , '']

  1. Fatal error: Uncaught TypeError: Unsupported operand types: PyStr * int in /home/mrpzx/git/phpy/phpy-examples/30s/python-code/to-roman-numeral.php:12
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function to_roman_numeral($num) {
    $lookup = new PyList([[1000, "M"], [900, "CM"], [500, "D"], [400, "CD"], [100, "C"], [90, "XC"], [50, "L"], [40, "XL"], [10, "X"], [9, "IX"], [5, "V"], [4, "IV"], [1, "I"]]);
    $res = "";
    $__iter = PyCore::iter($lookup);
    while($current = PyCore::next($__iter)) {
        [$n, $roman] = $current;
        [$d, $num] = PyCore::divmod($num, $n);
        $res += $roman * $d;    
    }
    return $res;
}


to_roman_numeral(3);
to_roman_numeral(11);
to_roman_numeral(1998);


def to_roman_numeral(num):
  lookup = [
    (1000, 'M'),
    (900, 'CM'),
    (500, 'D'),
    (400, 'CD'),
    (100, 'C'),
    (90, 'XC'),
    (50, 'L'),
    (40, 'XL'),
    (10, 'X'),
    (9, 'IX'),
    (5, 'V'),
    (4, 'IV'),
    (1, 'I'),
  ]
  res = ''
  for (n, roman) in lookup:
    (d, num) = divmod(num, n)
    res += roman * d
  return res

to_roman_numeral(3) # 'III'
to_roman_numeral(11) # 'XI'
to_roman_numeral(1998) # 'MCMXCVIII'

  1. Fatal error: Uncaught TypeError: Unsupported operand types: PyList + array in /home/mrpzx/git/phpy/phpy-examples/30s/python-code/union-by.php:15
<?php
$operator = PyCore::import("operator");
$builtins = PyCore::import("builtins");

function union_by($a, $b, $fn) {
    $_a = PyCore::set(PyCore::map($fn, $a));
    return PyCore::list(PyCore::set($a + (function($b) {
        $___ = [];
        $elts = [];
        foreach($b as $item) {
            $elts[0] = $item;
        }
        $___[] = $elts;
        return $___;
    })($b)));
}


$floor = PyCore::import('math')->floor;
union_by(new PyList([2.1]), new PyList([1.2, 2.3]), $floor);


def union_by(a, b, fn):
  _a = set(map(fn, a))
  return list(set(a + [item for item in b if fn(item) not in _a]))

from math import floor

union_by([2.1], [1.2, 2.3], floor) # [2.1, 1.2]

以上python代码来自 https://github.com/Chalarangelo/30-seconds-of-code/tree/master/content/snippets/python/s,相关提取、转换、测试代码如下

  • md.php
<?php

$files = glob('python-md/*.md');
array_map(function ($file) {
    preg_match_all('/```py([\s\S]+?)```/', file_get_contents($file), $matches);
    file_put_contents(substr($file, 0, -3) . '.py', implode("\n\n", $matches[1]));
}, $files);
  • py.php
<?php

$files = glob('python-code/*.py');
array_map(function ($file) {
    file_put_contents(substr($file, 0, -3) . '.php', convert(file_get_contents($file)));
}, $files);

function convert($code)
{
    return json_decode(request('https://swoole.com/py2php/convert.php', 'POST', ['code' => $code])[0])?->data?->code;
}

/**
 * http request
 * from swoole/ide-helper
 * @param string $url 
 * @param string $method 
 * @param mixed $data 
 * @param array $options 
 * @param null|array $headers 
 * @param null|array $cookies
 * @return array 
 */
function request(
    string $url,
    string $method = 'GET',
    $data = null,
    array $options = ['timeout' => 30],
    array $headers = null,
    array $cookies = null
): array {
    $ch = curl_init($url);
    if (empty($ch)) {
        throw new \Exception('failed to curl_init');
    }
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($method));
    if ($data) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    }
    if ($headers) {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }
    if ($cookies) {
        $cookie_str = '';
        foreach ($cookies as $k => $v) {
            $cookie_str .= "{$k}={$v}; ";
        }
        curl_setopt($ch, CURLOPT_COOKIE, $cookie_str);
    }
    if (isset($options['timeout'])) {
        if (is_float($options['timeout'])) {
            curl_setopt($ch, CURLOPT_TIMEOUT_MS, intval($options['timeout'] * 1000));
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, intval($options['timeout'] * 1000));
        } else {
            curl_setopt($ch, CURLOPT_TIMEOUT, intval($options['timeout']));
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, intval($options['timeout']));
        }
    }
    if (isset($options['connect_timeout'])) {
        if (is_float($options['connect_timeout'])) {
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, intval($options['connect_timeout'] * 1000));
        } else {
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, intval($options['connect_timeout']));
        }
    }
    if (isset($options['verify'])) {
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // 从证书中检查SSL加密算法是否存在
        // curl_setopt($ch, CURLOPT_SSLVERSION, 2);//设置SSL协议版本号
    }
    $body = curl_exec($ch);
    if ($body !== false) {
        return [$body, curl_getinfo($ch, CURLINFO_HTTP_CODE)];
    }
    throw new \Exception(curl_error($ch), curl_errno($ch));
}
  • test.php
<?php

$files = glob('python-code/*.php');

$i = 0;
$errs = [];
array_map(function ($file) use (&$i, &$errs) {
    $proc = proc_open('php ' . $file, [0 => STDIN, 1 => ['pipe', 'w'], 2 => ['redirect', 1]], $pipes);
    $stdout = stream_get_contents($pipes[1]);
    $status = proc_get_status($proc);
    proc_close($proc);

    if ($status['exitcode']) {
        $msg = explode("\n", trim($stdout))[0];
        if (!preg_match('/(.+?)in \/home.+?\s*(on line \d+)/', $msg, $match)) {
            $match = ['', $msg];
        }
        if (isset($errs[$match[1]])) {
            return;
        }
        $errs[$match[1]] = 0;
        echo (++$i) . '. ', $match[1], ' ', $match[2] ?? '', PHP_EOL;

        $pycode = file_get_contents(substr($file, 0, -4) . '.py');
        $phpcode = file_get_contents($file);
        echo <<<CODE
\```php
$phpcode
\```
CODE;
        echo PHP_EOL;
        echo <<<CODE
\```python
$pycode
\```
CODE;
        echo PHP_EOL;
    }
}, $files);
\```

he426100 avatar Dec 29 '23 05:12 he426100

正在尝试解决。

相当一部分的代码可能无法在 php 中很好地实现。

  1. 函数捕获的问题,例子 2 ,PHP 必须要显式传递,或者使用 global 变量,但是 global 不是正确的实现方式
  2. 函数重定义,PHP 不支持重定义,例子 14
  3. 运算符号重载,例如 PyList() + PyList ,PHP 不支持运算符重载
  4. Generator 语法,暂时无法支持
  5. 字符串方法,常量字符串会作为 PHP 的原生类型,需要转为 PyStr 才可以使用方法
  6. 类型符号,例如 int、tuple ,被转为 $int, $tuple ,Python 可以直接传递,而 PHP 里是不支持的,暂时不好解决

可以解决,并且已解决的问题:

  1. fstring 中的日期格式化
  2. 函数定义中的参数默认值

matyhtf avatar Aug 29 '24 08:08 matyhtf