小编mar*_*rco的帖子

通过对象引用传递良好实践

我来自 C++,在使用 Python 编程时,我很难获得安全感(例如拼写错误可能会导致极难发现错误,但这不是重点)。在这里,我想了解如何通过坚持良好的做法来避免做可怕的事情。

下面的简单函数在 C++ 中完全没问题,但在 Python 中却创建了我只能称之为怪物的东西。

def fun(x): 
    x += 1
    x = x + 1
    return x
Run Code Online (Sandbox Code Playgroud)

当我呼唤它时

var1 = 1;
print(fun(var1), var1)

var2 = np.array([1]);
print(fun(var2), var2)
Run Code Online (Sandbox Code Playgroud)

我明白了

3 1
[3] [2]
Run Code Online (Sandbox Code Playgroud)

除了缺乏同质行为(这已经很糟糕)之外,第二种情况尤其可怕。外部变量仅被部分指令修改!

我详细地知道为什么会发生这种情况。所以这不是我的问题。关键是,在构建复杂的程序时,我不想对所有这些依赖于上下文且高度隐含的技术细节格外小心。

必须有一些我可以严格遵守的良好实践,以防止我无意中生成上述代码。我可以想办法,但它们似乎使代码过于复杂,使 C++ 看起来像是一种更高级的语言。

我应该遵循什么好的做法来避免这种可怕的情况?

谢谢!

[编辑]一些澄清:我所困扰的是Python在创建临时变量时做出了依赖于类型和上下文的选择。再说一次,我知道规则。然而,在 C++ 中,选择是由程序员完成的,并且在整个函数中都是清晰的,而在 Python 中则不是这样。Python 要求程序员了解对参数执行的操作的一些技术细节,以便弄清楚此时 Python 是在处理临时变量还是原始变量。

请注意,我构造了一个函数,它既返回一个值,又具有副作用,只是为了表明我的观点。

要点是,程序员可能希望编写该函数以产生副作用(没有 return 语句),并且在该函数的中途,Python 决定构建一个临时函数,因此不会应用某些副作用。另一方面,程序员可能不想要副作用,而是会得到一些副作用(而且很难预测)。

在 C++ 中,上述内容的处理简单明了。在 Python 中,这是相当技术性的,需要知道什么触发临时变量的生成,什么不触发临时变量的生成。当我需要向我的学生解释这一点时,我想给他们一个简单的规则,以防止他们陷入这些陷阱。

python pass-by-reference

5
推荐指数
1
解决办法
927
查看次数

C++ 友元函数不被识别为具有模板专业化的友元

我试图将一个函数声明为具有受保护成员的类模板的友元。下面是一个最小的例子。

template<int N> class myClass{
public:
    friend void f(const myClass& c);
protected:
    int a;
};
Run Code Online (Sandbox Code Playgroud)

如果我现在将函数定义为

template<int N> void f(const myClass<N>& c){
    std::cout << c.a;
};
Run Code Online (Sandbox Code Playgroud)

然后就可以了。

但是如果我使用模板专业化

template<int N> void f(const myClass<N>& c);
template<> void f<1>(const myClass<1>& c){
    std::cout << c.a;
};
Run Code Online (Sandbox Code Playgroud)

它不再承认f自己是朋友,并抱怨说自己a是受保护的成员。

为什么会发生这种情况?我究竟做错了什么?

c++ templates friend specialization

3
推荐指数
1
解决办法
85
查看次数