5个有趣的Python小知识,返回结果让人出乎意料~

本文深入探讨了Python中五个令人意想不到的小特性,包括字符串驻留的条件、相同值的不可变对象如何处理、对象销毁顺序的奥秘、for循环的工作原理,以及生成器表达式的执行时机。这些特性虽小,但能显著提升对Python的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 字符串驻留

In [1]: a = 'something'
    ...: b = 'some'+'thing'
    ...: id(a)==id(b)
Out[1]: True

如果上面例子返回True,但是下面例子为什么是False:

In [1]: a = '@zglg.com'

In [2]: b = '@zglg'+'.com'

In [3]: id(a)==id(b)
Out[3]: False

这与Cpython 编译优化相关,行为称为字符串驻留,但驻留的字符串中只包含字母,数字或下划线。

2 相同值的不可变对象

In [5]: d = {}
    ...: d[1] = 'java'
    ...: d[1.0] = 'python'

In [6]: d
Out[6]: {1: 'python'}

### key=1,value=java的键值对神器消失了
In [7]: d[1]
Out[7]: 'python'
In [8]: d[1.0]
Out[8]: 'python'

这是因为具有相同值的不可变对象在Python中始终具有相同的哈希值

由于存在哈希冲突,不同值的对象也可能具有相同的哈希值。

3 对象销毁顺序

创建一个类SE:

class SE(object):
  def __init__(self):
    print('init')
  def __del__(self):
    print('del')

创建两个SE实例,使用is判断:

In [63]: SE() is SE()
init
init
del
del
Out[63]: False

创建两个SE实例,使用id判断:

In [64]: id(SE()) == id(SE())
init
del
init
del
Out[64]: True

调用id函数, Python 创建一个 SE 类的实例,并使用id函数获得内存地址后,销毁内存丢弃这个对象。

当连续两次进行此操作, Python会将相同的内存地址分配给第二个对象,所以两个对象的id值是相同的.

但是is行为却与之不同,通过打印顺序就可以看到。

4 充分认识for

In [65]: for i in range(5):
    ...:   print(i)
    ...:   i = 10
0
1
2
3
4

为什么不是执行一次就退出?

按照for在Python中的工作方式, i = 10 并不会影响循环。range(5)生成的下一个元素就被解包,并赋值给目标列表的变量i.

5 认识执行时机

array = [1, 3, 5]
g = (x for x in array if array.count(x) > 0)

g为生成器,list(g)后返回[1,3,5],因为每个元素肯定至少都出现一次。所以这个结果这不足为奇。但是,请看下例:

array = [1, 3, 5]
g = (x for x in array if array.count(x) > 0)
array = [5, 7, 9]

请问,list(g)等于多少?这不是和上面那个例子结果一样吗,结果也是[1,3,5],但是:

In [74]: list(g)
Out[74]: [5]

这有些不可思议~~ 原因在于:

生成器表达式中, in 子句在声明时执行, 而条件子句则是在运行时执行。

所以代码:

array = [1, 3, 5]
g = (x for x in array if array.count(x) > 0)
array = [5, 7, 9]

等价于:

g = (x for x in [1,3,5] if [5,7,9].count(x) > 0)

看明白吗?

以上就是五个Python小特性,都很有意思,结果确实出乎意料。

相信了解这些好玩的特性后,大家对Python的认识更近一步了,恭喜大家。


阅读更多:

Python的 global 到底干嘛的?

点击阅读原文,了解更多小知识

<think>好的,我现在需要解决用户在Simulink中使用Matlab Function模块时运行结果不符合预期的问题。首先,我应该回忆一下相关的知识,并结合用户提供的引用资料来分析可能的原因和解决方法。 用户提到了五个引用,其中引用1提到Matlab Function模块在变量输入或赋值上有特殊限制,可能和Interpreted Matlab Function不同。引用2指出某些函数可能需要用coder.extrinsic声明,或者换用Interpreted模块。引用3提到路径问题,不能在安装目录下操作。引用4展示了如何调用子函数,可能需要检查函数参数是否正确。引用5提到persistent关键字和触发器的使用,可能涉及变量初始化问题。 首先,常见的原因可能有变量作用域或初始化问题。比如,用户可能在函数内部使用了persistent变量,但未正确初始化,导致每次运行结果累积。例如,引用5中的示例,persistent变量如果没有初始化,可能会保留之前的值,导致输出不符合预期。需要检查是否有persistent或global变量未正确初始化。 其次,函数调用问题。Matlab Function模块不支持某些MATLAB函数,可能需要用coder.extrinsic声明。比如引用2提到的,如果用户调用了不支持的内置函数,必须声明或更换模块。此外,用户自定义的子函数是否正确调用,如引用4中的例子,参数传递是否正确,函数名是否匹配。 然后是路径问题。如引用3所述,如果模型保存在Matlab安装目录下,可能导致权限问题,需要更换工作目录。这可能导致函数无法正确加载或执行。 另外,输入输出端口配置可能错误。检查模块的输入信号是否与函数定义的参数匹配,数据类型是否正确。例如,用户可能在函数中期望两个输入参数,但Simulink模块只连接了一个信号,导致参数错误。 还有可能触发方式设置不当。默认情况下,Matlab Function模块是采样时间驱动,如果用户需要事件触发,可能需要添加trigger,如引用5提到的。如果触发方式不对,函数可能未按预期执行。 仿真步长设置也可能有影响。如果用户使用固定步长,而函数内部涉及连续时间运算,可能导致计算错误。需要确认步长是否合适。 此外,代码生成限制。Matlab Function模块生成的代码可能有严格的数据类型限制,例如不支持动态类型或某些矩阵操作。用户若使用了不支持的语法,如动态数组大小变化,可能导致错误。 可能的解决步骤:首先检查函数内部变量初始化,尤其是persistent变量;确认是否使用了不支持的函数,必要时用coder.extrinsic声明;验证输入输出端口配置是否正确;检查工作目录是否在非安装路径;调整触发方式或仿真步长;替换不支持的函数或改用Interpreted模块。 最后,用户可能需要调试,如添加disp语句输出中间变量值,或使用断点检查变量状态。但由于Simulink的限制,调试可能较困难,可以尝试简化模型逐步排查。</think>### Simulink中Matlab Function块运行结果不符合预期的原因及解决方法 #### 一、变量作用域与初始化问题 1. **Persistent变量未初始化** Matlab Function模块中若使用`persistent`声明静态变量,需在首次调用时初始化,否则会保留前次仿真结果。例如: ```matlab function y = myfunc() persistent count if isempty(count) count = 0; % 必须初始化 end count = count + 1; y = count; ``` 若未初始化,可能导致结果累积而非每次仿真重置[^5]。 2. **全局变量冲突** 使用`global`关键字时需确保变量在不同模块中的定义一致,避免与其他模块或基础工作区变量冲突。 --- #### 二、函数调用与语法限制 1. **不支持的内置函数** Matlab Function模块对部分MATLAB函数(如图形函数`plot`)有限制,需通过`coder.extrinsic('函数名')`声明外部函数: ```matlab function y = myfunc() coder.extrinsic('plot'); % 声明外部函数 plot(...); ``` 若仍不兼容,可改用*Interpreted Matlab Function*模块[^2]。 2. **子函数调用错误** 确保子函数定义在同一个文件内且参数传递正确。例如: ```matlab function Predyy = mainFunc(input, Time) Predyy = subFunc1(input) + subFunc2(Time); % 子函数名需匹配 end function A = subFunc1(x) A = x * 100; end ``` 若子函数参数类型不匹配(如期望标量却输入向量),会导致计算错误[^4]。 --- #### 三、输入输出配置问题 1. **端口数量/数据类型不匹配** - 检查模块输入端口数量是否与函数定义参数一致。 - 确认输入信号数据类型(如`double`、`int32`)与函数预期一致,必要时添加类型转换模块。 2. **输出未完全赋值** Matlab Function要求所有代码路径必须对输出变量赋值。例如: ```matlab function y = myfunc(cond) if cond > 0 y = 1; % 条件为真时赋值 else y = 0; % 必须覆盖所有情况 end ``` --- #### 四、仿真环境与路径问题 1. **工作目录权限冲突** 避免在Matlab安装目录(如`D:\Program Files\...`)中保存模型,否则会因权限问题导致函数无法执行。需将模型移至用户目录(如`D:\MyProjects`)[^3]。 2. **仿真步长与触发方式** - 若函数依赖时间连续计算,需检查仿真步长(Solver配置)是否过大致使精度不足。 - 若需事件触发,需在模块属性中添加`trigger`,并选择触发类型(如上升沿)[^5]。 --- #### 五、调试与验证方法 1. **添加调试输出** 在函数中插入`disp()`语句输出中间变量值: ```matlab function y = myfunc(x) disp(['Input x: ', num2str(x)]); % 控制台输出x的值 y = x * 2; ``` 2. **简化模型验证逻辑** 创建最小可复现模型,仅保留必要输入和Matlab Function模块,逐步排查问题。 3. **对比Interpreted模块** 暂时替换为*Interpreted Matlab Function*模块,若结果正确,则原问题可能由代码生成限制导致[^2]。 --- #### 六、代码生成限制的典型场景 | **限制类型** | **示例** | **解决方案** | |----------------------|-------------------------------|---------------------------------------| | 动态内存分配 | 使用变长数组`a = []` | 预定义固定大小数组 | | 递归函数 | 函数内部调用自身 | 改用循环结构 | | 隐式类型转换 | `uint8`与`double`混合运算 | 显式转换类型(如`double(x)`) | | 复杂矩阵操作 | 使用`cell`数组或高维矩阵 | 改用基本矩阵结构 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值