Python 哪个类拥有方法和属性

Python 哪个类拥有方法和属性,python,inheritance,attributes,self,Python,Inheritance,Attributes,Self,假设我们有以下代码: class C(CC): a = 1 b = 2 def __init__(self): self.x = None self.y = 1 如何在Python中快速找到属性或方法的定义位置?如果它属于祖先类,或者它是类C的方法。您可以看到属性a、b、x、y。它们必须属于C类吗?或者它们可以来自祖先类?何时将类型指定给变量 为什么不用呢 class C(CC): a = 1 b = 2 x = None y = 1 class

假设我们有以下代码:

class C(CC):
  a = 1
  b = 2
  def __init__(self):
    self.x = None
    self.y = 1
如何在Python中快速找到属性或方法的定义位置?如果它属于祖先类,或者它是类C的方法。您可以看到属性
a、b、x、y
。它们必须属于C类吗?或者它们可以来自祖先类?何时将类型指定给变量

为什么不用呢

class C(CC):
  a = 1
  b = 2
  x = None
  y = 1
class C(CC):
  a = 1
  b = 2
  x = None
  y = 1

谢谢

在第一个示例中,
a
b
是C类对象的属性。(考虑“静态”属性。)和
x
y
是C实例的属性。(因此,常规实例属性。)

在第二个示例中,所有四个都是C的属性,而不是它的实例的属性

在Python中,您不能“声明”由特定类定义的属性,这意味着没有要继承的属性定义。(或多或少,但我不打算通过引入
\uuuuuuuuuuuuuuuuuuuuuuuuu
来搅乱局面)。您可以通过搜索“def method_name(”)来查找方法定义,方法定义与大多数OO语言一样是继承的

令人困惑的是,您可以通过类的实例访问类属性,然后如果为该属性指定新值,则会创建一个新的实例属性:

In [1]: class C(object): a=1
In [2]: c1 = C()

In [3]: c1.a
Out[3]: 1

In [5]: c1.__dict__
Out[5]: {}

In [6]: c1.a=2

In [7]: c1.__dict__
Out[7]: {'a': 2}

In [8]: c2 = C()

In [9]: c2.a
Out[9]: 1

它允许您使用类属性为实例属性提供默认值。但我不认为这是一件非常常见的事情–我倾向于使用默认值作为
\uuuu init\uuuu()
参数。

在第一个示例中,
a
b
是C类对象的属性。(想想“静态”属性。)和
x
y
是C实例的属性(因此,常规实例属性)

在第二个示例中,所有四个都是C的属性,而不是它的实例的属性

在Python中,您不能“声明”由特定类定义的属性,这意味着没有要继承的属性定义(或多或少,但我不会通过引入
\uuuuuu slots\uuuu
)来混淆视听。您可以通过搜索“def method\u name(”和大多数OO语言一样,方法定义是继承的

令人困惑的是,您可以通过类的实例访问类属性,然后如果为该属性指定新值,则会创建一个新的实例属性:

In [1]: class C(object): a=1
In [2]: c1 = C()

In [3]: c1.a
Out[3]: 1

In [5]: c1.__dict__
Out[5]: {}

In [6]: c1.a=2

In [7]: c1.__dict__
Out[7]: {'a': 2}

In [8]: c2 = C()

In [9]: c2.a
Out[9]: 1
它允许您使用类属性为实例属性提供默认值。但我不认为这是一件非常常见的事情–我倾向于使用默认值作为
\uuuu init\uuuuuuuuuuuuo()
参数。

为什么不使用默认值呢

class C(CC):
  a = 1
  b = 2
  x = None
  y = 1
class C(CC):
  a = 1
  b = 2
  x = None
  y = 1
这不是同一件事。它有四个类级属性,由类
C
的所有对象共享

class C(CC):
  a = 1
  b = 2
  def __init__(self):
    self.x = None
    self.y = 1
这是不同的。它有两个类级属性,由类
C
的所有对象共享,两个实例变量对类
C
的每个对象都是唯一的

class C(CC):
  a = 1
  b = 2
  def __init__(self):
    self.x = None
    self.y = 1
您的两个代码示例非常不同。它们无法进行比较

为了回答您的另一个问题,我们使用GREP和其他工具来搜索源代码。这很简单。

为什么不使用GREP和其他工具呢

class C(CC):
  a = 1
  b = 2
  x = None
  y = 1
class C(CC):
  a = 1
  b = 2
  x = None
  y = 1
这不是同一件事。它有四个类级属性,由类
C
的所有对象共享

class C(CC):
  a = 1
  b = 2
  def __init__(self):
    self.x = None
    self.y = 1
这是不同的。它有两个类级属性,由类
C
的所有对象共享,两个实例变量对类
C
的每个对象都是唯一的

class C(CC):
  a = 1
  b = 2
  def __init__(self):
    self.x = None
    self.y = 1
您的两个代码示例非常不同。它们无法进行比较


为了回答你的另一个问题,我们使用GREP和其他工具来搜索源代码。这很简单。

那么你可以变得更有趣:
C.a=3
;然后
c1.a==2
,因为它是它自己的实例变量,
c2.a==3
,因为它是在原型链中查找回类的。稍后我将n其他函数是对
self.x.someMethod()
的调用,因此x可能是某个对象,但在什么地方定义了x实际是什么?在某个继承类中?或者它可以是什么?你说“令人困惑”,但我从未发现它是这样的(即使在我第一次接触Python时)。这纯粹是一个原型链。只要你在实例中设置了一个值,它就在实例中设置了,就是这样。@xralf:
x
可以在任何地方定义。我的意思是在任何地方。
c4=C();c4.x=Q()。它通常更可能被定义在类或超类中,但它不是必需的。因为一些原因,我觉得它很混乱。一个是Python有一个基于类的对象模型,所以你不希望一个原型链用于数据。另一个是行为不同于C++ <代码>静态< /COD>及其DES。另一个原因是,我期望对象的“数据”在其
\uuuuu dict\uuuuu
/
\uuuuuuu slots\uuuuuu
中(期望和/或想要,例如自动预打印数据),因此它可以(理论上)甚至对于不依赖该行为的Python用户也不例外。我知道该行为在Python元模型的上下文中是如何有意义和必要的,但我不喜欢它用于数据。然后你会变得更有趣:
C.a=3
;然后
c1.a==2
,因为它是它自己的实例变量,
c2.a==3
它在原型链中找到了类。后来在其他函数中调用了
self.x.someMethod()
,因此x可能是某个对象,但在哪里定义了x实际是什么?在某个继承类中?或者它可以是什么?你说“令人困惑”,但我从未发现它是这样的(即使在我第一次接触Python时)。这纯粹是一个原型链。只要你在实例中设置了一个值,它就在实例中设置了,就是这样。@xralf:
x
可以在任何地方定义。我的意思是在任何地方。
c4=C();c4.x=Q()
。它通常更可能在