GVKun编程网logo

在Python中评估布尔表达式(python布尔值判断)

10

在这里,我们将给大家分享关于在Python中评估布尔表达式的知识,让您更了解python布尔值判断的本质,同时也会涉及到如何更有效地2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结

在这里,我们将给大家分享关于在Python中评估布尔表达式的知识,让您更了解python布尔值判断的本质,同时也会涉及到如何更有效地2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (t、2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (true)、& (AND)、 | (OR) 和 ^ (XOR) 符号组成。、2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (true)、& (AND)、 | (OR) 和 ^ (XOR...、IronPython中大规模评估表达式的表现的内容。

本文目录一览:

在Python中评估布尔表达式(python布尔值判断)

在Python中评估布尔表达式(python布尔值判断)

对象在Python中评估的真值是多少?

相关问题

  • Python中对象的布尔值:有关覆盖对象评估方式的讨论

答案1

小编典典

可以测试任何对象的真值,以在if或while条件中使用或用作以下布尔运算的操作数。以下值为“假”:

  • 没有

  • 任何数值类型的零,例如00L0.00j

  • 任何空序列,例如''''()[]

  • 任何空映射,例如{}

  • 用户定义的类的实例,如果该类定义了__nonzero__()__len__()方法,则该方法返回整数0或bool
    value时False

所有其他值都被视为true,因此许多类型的对象始终为true。除非另有说明,否则具有布尔结果的操作和内置函数始终返回0或Falsefalse,返回1或Truetrue。(重要的例外:布尔运算符“或”和“和”始终返回其操作数之一。)

https://docs.python.org/2/library/stdtypes.html#truth-value-
testing

如前所述,您可以通过修改非零值来覆盖自定义对象。

2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (t

2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (t

2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (true)、& (AND)、 | (OR) 和 ^ (XOR) 符号组成。实现一个函数,算出有几种可使该表达式得出 result 值的括号方法。


福大大 答案 2021-06-03:


方法一:递归。

方法二:动态规划。


代码用 golang 编写。代码如下:

package main
import "fmt"
func main() {
express := "1&1&1" desired := 1 ret0 := countEval0(express, desired) ret1 := countEval1(express, desired) ret2 := countEval2(express, desired) fmt.Println(ret0, ret1, ret2)
}
func countEval0(express string, desired int) int { if express == "" { return 0 } N := len(express) dp := make([][]*Info, N) for i := 0; i < N; i++ { dp[i] = make([]*Info, N) } allInfo := ff(express, 0, len(express)-1, dp) return twoSelectOne(desired == 1, allInfo.t, allInfo.f)}
type Info struct { t int f int}
func twoSelectOne(c bool, a int, b int) int { if c { return a } else { return b }}
// 限制:// L...R上,一定有奇数个字符// L位置的字符和R位置的字符,非01,不能是逻辑符号!// 返回str[L...R]这一段,为true的方法数,和false的方法数func ff(str string, L int, R int, dp [][]*Info) *Info { if dp[L][R] != nil { return dp[L][R] } t := 0 f := 0 if L == R { t = twoSelectOne(str[L] == ''1'', 1, 0) f = twoSelectOne(str[L] == ''0'', 1, 0) } else { // L..R >=3 // 每一个种逻辑符号,split枚举的东西 // 都去试试最后结合 for split := L + 1; split < R; split += 2 { leftInfo := ff(str, L, split-1, dp) rightInfo := ff(str, split+1, R, dp) a := leftInfo.t b := leftInfo.f c := rightInfo.t d := rightInfo.f switch str[split] { case ''&'': t += a * c f += b*c + b*d + a*d break case ''|'': t += a*c + a*d + b*c f += b * d break case ''^'': t += a*d + b*c f += a*c + b*d break } }
} dp[L][R] = &Info{t, f} return dp[L][R]}
func countEval1(express string, desired int) int { if express == "" { return 0 } return f(express, desired, 0, len(express)-1)}
func f(str string, desired int, L int, R int) int { if L == R { if str[L] == ''1'' { return desired } else { return desired ^ 1 } } res := 0 if desired == 1 { for i := L + 1; i < R; i += 2 { switch str[i] { case ''&'': res += f(str, 1, L, i-1) * f(str, 1, i+1, R) break case ''|'': res += f(str, 1, L, i-1) * f(str, 0, i+1, R) res += f(str, 0, L, i-1) * f(str, 1, i+1, R) res += f(str, 1, L, i-1) * f(str, 1, i+1, R) break case ''^'': res += f(str, 1, L, i-1) * f(str, 0, i+1, R) res += f(str, 0, L, i-1) * f(str, 1, i+1, R) break } } } else { for i := L + 1; i < R; i += 2 { switch str[i] { case ''&'': res += f(str, 0, L, i-1) * f(str, 1, i+1, R) res += f(str, 1, L, i-1) * f(str, 0, i+1, R) res += f(str, 0, L, i-1) * f(str, 0, i+1, R) break case ''|'': res += f(str, 0, L, i-1) * f(str, 0, i+1, R) break case ''^'': res += f(str, 1, L, i-1) * f(str, 1, i+1, R) res += f(str, 0, L, i-1) * f(str, 0, i+1, R) break } } } return res}
func countEval2(express string, desired int) int { if express == "" { return 0 } N := len(express) dp := make([][][]int, 2) for i := 0; i < 2; i++ { dp[i] = make([][]int, N) for j := 0; j < N; j++ { dp[i][j] = make([]int, N) } } dp[0][0][0] = twoSelectOne(express[0] == ''0'', 1, 0) dp[1][0][0] = dp[0][0][0] ^ 1 for i := 2; i < len(express); i += 2 { dp[0][i][i] = twoSelectOne(express[i] == ''1'', 0, 1) dp[1][i][i] = twoSelectOne(express[i] == ''0'', 0, 1) for j := i - 2; j >= 0; j -= 2 { for k := j; k < i; k += 2 { if express[k+1] == ''&'' { dp[1][j][i] += dp[1][j][k] * dp[1][k+2][i] dp[0][j][i] += (dp[0][j][k]+dp[1][j][k])*dp[0][k+2][i] + dp[0][j][k]*dp[1][k+2][i] } else if express[k+1] == ''|'' { dp[1][j][i] += (dp[0][j][k]+dp[1][j][k])*dp[1][k+2][i] + dp[1][j][k]*dp[0][k+2][i] dp[0][j][i] += dp[0][j][k] * dp[0][k+2][i] } else { dp[1][j][i] += dp[0][j][k]*dp[1][k+2][i] + dp[1][j][k]*dp[0][k+2][i] dp[0][j][i] += dp[0][j][k]*dp[0][k+2][i] + dp[1][j][k]*dp[1][k+2][i] } } } } return dp[desired][0][N-1]}

执行结果如下:

***

[左神 java 代码](https://gitee.com/moonfdd/coding-for-great-offer/blob/main/src/class10/Code05_BooleanEvaluation.java)



本文分享自微信公众号 - 福大大架构师每日一题(gh_bbe96e5def84)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与 “OSC 源创计划”,欢迎正在阅读的你也加入,一起分享。

2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (true)、& (AND)、 | (OR) 和 ^ (XOR) 符号组成。

2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (true)、& (AND)、 | (OR) 和 ^ (XOR) 符号组成。

2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (true)、& (AND)、 | (OR) 和 ^ (XOR) 符号组成。实现一个函数,算出有几种可使该表达式得出 result 值的括号方法。

福大大 答案2021-06-03:

方法一:递归。
方法二:动态规划。

代码用golang编写。代码如下:

package main

import "fmt"

func main() {

    express := "1&1&1"
    desired := 1
    ret0 := countEval0(express, desired)
    ret1 := countEval1(express, desired)
    ret2 := countEval2(express, desired)
    fmt.Println(ret0, ret1, ret2)

}

func countEval0(express string, desired int) int {
    if express == "" {
        return 0
    }
    N := len(express)
    dp := make([][]*Info, N)
    for i := 0; i < N; i++ {
        dp[i] = make([]*Info, N)
    }
    allInfo := ff(express, 0, len(express)-1, dp)
    return twoSelectOne(desired == 1, allInfo.t, allInfo.f)
}

type Info struct {
    t int
    f int
}

func twoSelectOne(c bool, a int, b int) int {
    if c {
        return a
    } else {
        return b
    }
}

// 限制:
// L...R上,一定有奇数个字符
// L位置的字符和R位置的字符,非0即1,不能是逻辑符号!
// 返回str[L...R]这一段,为true的方法数,和false的方法数
func ff(str string, L int, R int, dp [][]*Info) *Info {
    if dp[L][R] != nil {
        return dp[L][R]
    }
    t := 0
    f := 0
    if L == R {
        t = twoSelectOne(str[L] == ''1'', 1, 0)
        f = twoSelectOne(str[L] == ''0'', 1, 0)
    } else { // L..R >=3
        // 每一个种逻辑符号,split枚举的东西
        // 都去试试最后结合
        for split := L + 1; split < R; split += 2 {
            leftInfo := ff(str, L, split-1, dp)
            rightInfo := ff(str, split+1, R, dp)
            a := leftInfo.t
            b := leftInfo.f
            c := rightInfo.t
            d := rightInfo.f
            switch str[split] {
            case ''&'':
                t += a * c
                f += b*c + b*d + a*d
                break
            case ''|'':
                t += a*c + a*d + b*c
                f += b * d
                break
            case ''^'':
                t += a*d + b*c
                f += a*c + b*d
                break
            }
        }

    }
    dp[L][R] = &Info{t, f}
    return dp[L][R]
}

func countEval1(express string, desired int) int {
    if express == "" {
        return 0
    }
    return f(express, desired, 0, len(express)-1)
}

func f(str string, desired int, L int, R int) int {
    if L == R {
        if str[L] == ''1'' {
            return desired
        } else {
            return desired ^ 1
        }
    }
    res := 0
    if desired == 1 {
        for i := L + 1; i < R; i += 2 {
            switch str[i] {
            case ''&'':
                res += f(str, 1, L, i-1) * f(str, 1, i+1, R)
                break
            case ''|'':
                res += f(str, 1, L, i-1) * f(str, 0, i+1, R)
                res += f(str, 0, L, i-1) * f(str, 1, i+1, R)
                res += f(str, 1, L, i-1) * f(str, 1, i+1, R)
                break
            case ''^'':
                res += f(str, 1, L, i-1) * f(str, 0, i+1, R)
                res += f(str, 0, L, i-1) * f(str, 1, i+1, R)
                break
            }
        }
    } else {
        for i := L + 1; i < R; i += 2 {
            switch str[i] {
            case ''&'':
                res += f(str, 0, L, i-1) * f(str, 1, i+1, R)
                res += f(str, 1, L, i-1) * f(str, 0, i+1, R)
                res += f(str, 0, L, i-1) * f(str, 0, i+1, R)
                break
            case ''|'':
                res += f(str, 0, L, i-1) * f(str, 0, i+1, R)
                break
            case ''^'':
                res += f(str, 1, L, i-1) * f(str, 1, i+1, R)
                res += f(str, 0, L, i-1) * f(str, 0, i+1, R)
                break
            }
        }
    }
    return res
}

func countEval2(express string, desired int) int {
    if express == "" {
        return 0
    }
    N := len(express)
    dp := make([][][]int, 2)
    for i := 0; i < 2; i++ {
        dp[i] = make([][]int, N)
        for j := 0; j < N; j++ {
            dp[i][j] = make([]int, N)
        }
    }
    dp[0][0][0] = twoSelectOne(express[0] == ''0'', 1, 0)
    dp[1][0][0] = dp[0][0][0] ^ 1
    for i := 2; i < len(express); i += 2 {
        dp[0][i][i] = twoSelectOne(express[i] == ''1'', 0, 1)
        dp[1][i][i] = twoSelectOne(express[i] == ''0'', 0, 1)
        for j := i - 2; j >= 0; j -= 2 {
            for k := j; k < i; k += 2 {
                if express[k+1] == ''&'' {
                    dp[1][j][i] += dp[1][j][k] * dp[1][k+2][i]
                    dp[0][j][i] += (dp[0][j][k]+dp[1][j][k])*dp[0][k+2][i] + dp[0][j][k]*dp[1][k+2][i]
                } else if express[k+1] == ''|'' {
                    dp[1][j][i] += (dp[0][j][k]+dp[1][j][k])*dp[1][k+2][i] + dp[1][j][k]*dp[0][k+2][i]
                    dp[0][j][i] += dp[0][j][k] * dp[0][k+2][i]
                } else {
                    dp[1][j][i] += dp[0][j][k]*dp[1][k+2][i] + dp[1][j][k]*dp[0][k+2][i]
                    dp[0][j][i] += dp[0][j][k]*dp[0][k+2][i] + dp[1][j][k]*dp[1][k+2][i]
                }
            }
        }
    }
    return dp[desired][0][N-1]
}

执行结果如下:

图片


左神java代码

总结

以上是小编为你收集整理的2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (true)、& (AND)、 | (OR) 和 ^ (XOR) 符号组成。全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

原文地址:https://blog.csdn.net/weixin_48502062/article/details/117537426

2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (true)、& (AND)、 | (OR) 和 ^ (XOR...

2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (true)、& (AND)、 | (OR) 和 ^ (XOR...

2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (true)、& (AND)、 | (OR) 和 ^ (XOR) 符号组成。实现一个函数,算出有几种可使该表达式得出 result 值的括号方法。

福大大 答案2021-06-03:

方法一:递归。
方法二:动态规划。

代码用golang编写。代码如下:

package main

import "fmt"

func main() {
   

    express := "1&1&1"
    desired := 1
    ret0 := countEval0(express, desired)
    ret1 := countEval1(express, desired)
    ret2 := countEval2(express, desired)
    fmt.Println(ret0, ret1, ret2)

}

func countEval0(express string, desired int) int {
   
    if express == "" {
   
        return 0
    }
    N := len(express)
    dp := make([][]*Info, N)
    for i := 0; i < N; i++ {
   
        dp[i] = make([]*Info, N)
    }
    allInfo := ff(express, 0, len(express)-1, dp)
    return twoSelectOne(desired == 1, allInfo.t, allInfo.f)
}

type Info struct {
   
    t int
    f int
}

func twoSelectOne(c bool, a int, b int) int {
   
    if c {
   
        return a
    } else {
   
        return b
    }
}

// 限制:
// L...R上,一定有奇数个字符
// L位置的字符和R位置的字符,非0即1,不能是逻辑符号!
// 返回str[L...R]这一段,为true的方法数,和false的方法数
func ff(str string, L int, R int, dp [][]*Info) *Info {
   
    if dp[L][R] != nil {
   
        return dp[L][R]
    }
    t := 0
    f := 0
    if L == R {
   
        t = twoSelectOne(str[L] == ''1'', 1, 0)
        f = twoSelectOne(str[L] == ''0'', 1, 0)
    } else {
    // L..R >=3
        // 每一个种逻辑符号,split枚举的东西
        // 都去试试最后结合
        for split := L + 1; split < R; split += 2 {
   
            leftInfo := ff(str, L, split-1, dp)
            rightInfo := ff(str, split+1, R, dp)
            a := leftInfo.t
            b := leftInfo.f
            c := rightInfo.t
            d := rightInfo.f
            switch str[split] {
   
            case ''&'':
                t += a * c
                f += b*c + b*d + a*d
                break
            case ''|'':
                t += a*c + a*d + b*c
                f += b * d
                break
            case ''^'':
                t += a*d + b*c
                f += a*c + b*d
                break
            }
        }

    }
    dp[L][R] = &Info{
   t, f}
    return dp[L][R]
}

func countEval1(express string, desired int) int {
   
    if express == "" {
   
        return 0
    }
    return f(express, desired, 0, len(express)-1)
}

func f(str string, desired int, L int, R int) int {
   
    if L == R {
   
        if str[L] == ''1'' {
   
            return desired
        } else {
   
            return desired ^ 1
        }
    }
    res := 0
    if desired == 1 {
   
        for i := L + 1; i < R; i += 2 {
   
            switch str[i] {
   
            case ''&'':
                res += f(str, 1, L, i-1) * f(str, 1, i+1, R)
                break
            case ''|'':
                res += f(str, 1, L, i-1) * f(str, 0, i+1, R)
                res += f(str, 0, L, i-1) * f(str, 1, i+1, R)
                res += f(str, 1, L, i-1) * f(str, 1, i+1, R)
                break
            case ''^'':
                res += f(str, 1, L, i-1) * f(str, 0, i+1, R)
                res += f(str, 0, L, i-1) * f(str, 1, i+1, R)
                break
            }
        }
    } else {
   
        for i := L + 1; i < R; i += 2 {
   
            switch str[i] {
   
            case ''&'':
                res += f(str, 0, L, i-1) * f(str, 1, i+1, R)
                res += f(str, 1, L, i-1) * f(str, 0, i+1, R)
                res += f(str, 0, L, i-1) * f(str, 0, i+1, R)
                break
            case ''|'':
                res += f(str, 0, L, i-1) * f(str, 0, i+1, R)
                break
            case ''^'':
                res += f(str, 1, L, i-1) * f(str, 1, i+1, R)
                res += f(str, 0, L, i-1) * f(str, 0, i+1, R)
                break
            }
        }
    }
    return res
}

func countEval2(express string, desired int) int {
   
    if express == "" {
   
        return 0
    }
    N := len(express)
    dp := make([][][]int, 2)
    for i := 0; i < 2; i++ {
   
        dp[i] = make([][]int, N)
        for j := 0; j < N; j++ {
   
            dp[i][j] = make([]int, N)
        }
    }
    dp[0][0][0] = twoSelectOne(express[0] == ''0'', 1, 0)
    dp[1][0][0] = dp[0][0][0] ^ 1
    for i := 2; i < len(express); i += 2 {
   
        dp[0][i][i] = twoSelectOne(express[i] == ''1'', 0, 1)
        dp[1][i][i] = twoSelectOne(express[i] == ''0'', 0, 1)
        for j := i - 2; j >= 0; j -= 2 {
   
            for k := j; k < i; k += 2 {
   
                if express[k+1] == ''&'' {
   
                    dp[1][j][i] += dp[1][j][k] * dp[1][k+2][i]
                    dp[0][j][i] += (dp[0][j][k]+dp[1][j][k])*dp[0][k+2][i] + dp[0][j][k]*dp[1][k+2][i]
                } else if express[k+1] == ''|'' {
   
                    dp[1][j][i] += (dp[0][j][k]+dp[1][j][k])*dp[1][k+2][i] + dp[1][j][k]*dp[0][k+2][i]
                    dp[0][j][i] += dp[0][j][k] * dp[0][k+2][i]
                } else {
   
                    dp[1][j][i] += dp[0][j][k]*dp[1][k+2][i] + dp[1][j][k]*dp[0][k+2][i]
                    dp[0][j][i] += dp[0][j][k]*dp[0][k+2][i] + dp[1][j][k]*dp[1][k+2][i]
                }
            }
        }
    }
    return dp[desired][0][N-1]
}

执行结果如下:
图片


左神java代码

IronPython中大规模评估表达式的表现

IronPython中大规模评估表达式的表现

在C#-4.0应用程序中,我有一个具有相同长度的强类型IList字典 – 一个动态强类型列的表.
我希望用户根据将在所有行上聚合的可用列提供一个或多个( python-)表达式.在静态上下文中它将是:

IDictionary<string,IList> table;
// ...
IList<int> a = table["a"] as IList<int>;
IList<int> b = table["b"] as IList<int>;
double sum = 0;
for (int i = 0; i < n; i++)
    sum += (double)a[i] / b[i]; // Expression to sum up

对于n = 10 ^ 7,这在我的笔记本电脑上以0.270秒运行(win7 x64).对于具有两个int参数的委托替换表达式需要0.580秒,对于非类型委托,需要1.19秒.
用IronPython创建委托

IDictionary<string,IList> table;
// ...
var options = new Dictionary<string,object>();
options["Divisionoptions"] = PythonDivisionoptions.New;
var engine = Python.CreateEngine(options);
string expr = "a / b";
Func<int,int,double> f = engine.Execute("lambda a,b : " + expr);

IList<int> a = table["a"] as IList<int>;
IList<int> b = table["b"] as IList<int>;
double sum = 0;
for (int i = 0; i < n; i++)
    sum += f(a[i],b[i]);

它需要3.2秒(而使用Func< object,object,object>则需要5.1秒) – 因子4到5.5.这是我正在做的事情的预期开销吗?有什么可以改进的?

如果我有很多列,那么上面选择的方法就不够了.一种解决方案可以是确定每个表达式所需的列,并仅将它们用作参数.我尝试失败的另一个解决方案是使用ScriptScope并动态解析列.为此,我定义了一个RowIterator,它具有活动行的RowIndex和每列的属性.

class RowIterator
{
    IList<int> la;
    IList<int> lb;

    public RowIterator(IList<int> a,IList<int> b)
    {
        this.la = a;
        this.lb = b;
    }
    public int RowIndex { get; set; }

    public int a { get { return la[RowIndex]; } }
    public int b { get { return lb[RowIndex]; } }
}

ScriptScope可以从IDynamicMetaObjectProvider创建,我希望它可以通过C#的动态实现 – 但是在运行时engine.CreateScope(IDictionary)正在尝试调用,但失败了.

dynamic iterator = new RowIterator(a,b) as dynamic;
var scope = engine.CreateScope(iterator);
var expr = engine.CreateScriptSourceFromString("a / b").Compile();

double sum = 0;
for (int i = 0; i < n; i++)
{
    iterator.Index = i;
    sum += expr.Execute<double>(scope);
}

接下来,我尝试让RowIterator从DynamicObject继承并使其成为一个正在运行的示例 – 具有可怕的性能:158秒.

class DynamicRowIterator : DynamicObject
{
    Dictionary<string,object> members = new Dictionary<string,object>();
    IList<int> la;
    IList<int> lb;

    public DynamicRowIterator(IList<int> a,IList<int> b)
    {
        this.la = a;
        this.lb = b;
    }

    public int RowIndex { get; set; }
    public int a { get { return la[RowIndex]; } }
    public int b { get { return lb[RowIndex]; } }

    public override bool TryGetMember(GetMemberBinder binder,out object result)
    {
        if (binder.Name == "a") // Why does this happen?
        {
            result = this.a;
            return true;
        }
        if (binder.Name == "b")
        {
            result = this.b;
            return true;
        }
        if (base.TryGetMember(binder,out result))
            return true;
        if (members.TryGetValue(binder.Name,out result))
            return true;
        return false;
    }

    public override bool TrySetMember(SetMemberBinder binder,object value)
    {
        if (base.TrySetMember(binder,value))
            return true;
        members[binder.Name] = value;
        return true;
    }
}

我对使用属性名称调用TryGetMember感到惊讶.从文档中我可以预期,TryGetMember只会被调用未定义的属性.

可能为了一个明智的性能,我需要为我的RowIterator实现IDynamicMetaObjectProvider以使用动态CallSites,但是找不到适合我的例子.在我的实验中,我不知道如何在BindGetMember中处理__builtins__:

class Iterator : IDynamicMetaObjectProvider
{
    IList<int> la;
    IList<int> lb;

    public Iterator(IList<int> a,IList<int> b)
    {
        this.la = a;
        this.lb = b;
    }
    public int RowIndex { get; set; }
    public int a { get { return la[RowIndex]; } }
    public int b { get { return lb[RowIndex]; } }

    public DynamicMetaObject GetMetaObject(Expression parameter)
    {
        return new MetaObject(parameter,this);
    }

    private class MetaObject : DynamicMetaObject
    {
        internal MetaObject(Expression parameter,Iterator self)
             : base(parameter,BindingRestrictions.Empty,self) { }

        public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
        {
            switch (binder.Name)
            {
                case "a":
                case "b":
                    Type type = typeof(Iterator);
                    string methodName = binder.Name;
                    Expression[] parameters = new Expression[]
                    {
                        Expression.Constant(binder.Name)
                    };
                    return new DynamicMetaObject(
                        Expression.Call(
                            Expression.Convert(Expression,LimitType),type.getmethod(methodName),parameters),BindingRestrictions.GetTypeRestriction(Expression,LimitType));
                default:
                    return base.BindGetMember(binder);
            }
        }
    }
}

我确定我上面的代码不是最理想的,至少它还没有处理列的IDictionary.对于如何改进设计和/或性能的任何建议,我将不胜感激.

解决方法

我还将IronPython的性能与C#实现进行了比较.表达式很简单,只需在指定的索引处添加两个数组的值即可.直接访问阵列提供了基线和理论最优.通过符号字典访问值仍然具有可接受的性能.

第三个测试从一个天真(和坏的意图)表达树创建一个委托,没有任何花哨的东西,如呼叫端缓存,但它仍然比IronPython更快.

通过IronPython脚本编写表达式需要花费最多的时间.我的探查器向我展示了大部分时间花在Pythonops.Getvariable,PythonDictionary.TryGetValue和Pythonops.TryGetBoundAttr上.我认为还有改进的余地.

时序:

>直达:00:00:00.0052680
>通过词典:00:00:00.5577922
>编译代表:00:00:03.2733377
>脚本:00:00:09.0485515

这是代码:

public static void PythonBenchmark()
    {
        var engine = Python.CreateEngine();

        int iterations = 1000;
        int count = 10000;

        int[] a = Enumerable.Range(0,count).ToArray();
        int[] b = Enumerable.Range(0,count).ToArray();

        Dictionary<string,object> symbols = new Dictionary<string,object> { { "a",a },{ "b",b } };

        Func<int,object> calculate = engine.Execute("lambda i: a[i] + b[i]",engine.CreateScope(symbols));

        var sw = Stopwatch.StartNew();

        int sum = 0;

        for (int iteration = 0; iteration < iterations; iteration++)
        {
            for (int i = 0; i < count; i++)
            {
                sum += a[i] + b[i];
            }
        }

        Console.WriteLine("Direct: " + sw.Elapsed);



        sw.Restart();
        for (int iteration = 0; iteration < iterations; iteration++)
        {
            for (int i = 0; i < count; i++)
            {
                sum += ((int[])symbols["a"])[i] + ((int[])symbols["b"])[i];
            }
        }

        Console.WriteLine("via Dictionary: " + sw.Elapsed);



        var indexExpression = Expression.Parameter(typeof(int),"index");
        var indexerMethod = typeof(IList<int>).getmethod("get_Item");
        var lookupMethod = typeof(IDictionary<string,object>).getmethod("get_Item");
        Func<string,Expression> getSymbolExpression = symbol => Expression.Call(Expression.Constant(symbols),lookupMethod,Expression.Constant(symbol));
        var addExpression = Expression.Add(
                                Expression.Call(Expression.Convert(getSymbolExpression("a"),typeof(IList<int>)),indexerMethod,indexExpression),Expression.Call(Expression.Convert(getSymbolExpression("b"),indexExpression));
        var compiledFunc = Expression.Lambda<Func<int,object>>(Expression.Convert(addExpression,typeof(object)),indexExpression).Compile();

        sw.Restart();
        for (int iteration = 0; iteration < iterations; iteration++)
        {
            for (int i = 0; i < count; i++)
            {
                sum += (int)compiledFunc(i);
            }
        }

        Console.WriteLine("Compiled Delegate: " + sw.Elapsed);



        sw.Restart();
        for (int iteration = 0; iteration < iterations; iteration++)
        {
            for (int i = 0; i < count; i++)
            {
                sum += (int)calculate(i);
            }
        }

        Console.WriteLine("Scripted: " + sw.Elapsed);
        Console.WriteLine(sum); // make sure cannot be optimized away
    }

今天关于在Python中评估布尔表达式python布尔值判断的介绍到此结束,谢谢您的阅读,有关2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (t、2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (true)、& (AND)、 | (OR) 和 ^ (XOR) 符号组成。、2021-06-03:布尔运算。给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (true)、& (AND)、 | (OR) 和 ^ (XOR...、IronPython中大规模评估表达式的表现等更多相关知识的信息可以在本站进行查询。

本文标签:

上一篇在Python的字段中以逗号读取CSV文件(python读csv文件有逗号转义)

下一篇Apache Ftp服务器与Android整合(apache ftp server)