简体   繁体   English

如何在 Python 中定义一个类?

[英]How can I define a class in Python?

Quite simple, I'm learning Python, and I can't find a reference that tells me how to write the following:很简单,我正在学习Python,但找不到告诉我如何编写以下内容的参考:

public class Team {
     private String name;
     private String logo;
     private int members;

     public Team(){}

     // Getters/setters
}

Later:之后:

Team team = new Team();
team.setName("Oscar");
team.setLogo("http://....");
team.setMembers(10);

That is a class Team with the properties: name/logo/members这是一个具有以下属性的类 Team:名称/徽标/成员

Edit编辑

After a few attempts I got this:经过几次尝试,我得到了这个:

class Team:
    pass

Later之后

team = Team()
team.name = "Oscar"
team.logo = "http://..."
team.members = 10

Is this the Python way?这是 Python 的方式吗? It feels odd (coming from a strongly typed language of course).感觉很奇怪(当然来自强类型语言)。

Here is what I would recommend:以下是我的建议:

class Team(object):
    def __init__(self, name=None, logo=None, members=0):
        self.name = name
        self.logo = logo
        self.members = members

team = Team("Oscar", "http://...", 10)

team2 = Team()
team2.name = "Fred"

team3 = Team(name="Joe", members=10)

Some notes on this:关于这个的一些注意事项:

  1. I declared that Team inherits from object .我声明Team继承自object This makes Team a "new-style class";这使得 Team 成为一个“新式班级”; this has been recommended practice in Python since it was introduced in Python 2.2.自 Python 2.2 引入以来,这一直是 Python 中的推荐做法。 (In Python 3.0 and above, classes are always "new-style" even if you leave out the (object) notation; but having that notation does no harm and makes the inheritance explicit.) Here's a Stack Overflow discussion of new-style classes. (在 Python 3.0 及更高版本中,即使您省略了(object)表示法,类也始终是“新式”的;但使用该表示法并没有什么害处,并使继承变得明确。)这是关于新式类的 Stack Overflow 讨论.

  2. It's not required, but I made the initializer take optional arguments so that you can initialize the instance on one line, as I did with team and team3 .这不是必需的,但我让初始化程序采用可选参数,以便您可以在一行上初始化实例,就像我对teamteam3 These arguments are named, so you can either provide values as positional parameters (as with team ) or you can use the argument= form as I did with team3 .这些参数是命名的,因此您可以提供值作为位置参数(与team ),或者您可以使用argument=形式,就像我对team3所做的team3 When you explicitly specify the name of the arguments, you can specify arguments in any order.当您明确指定参数的名称时,您可以按任意顺序指定参数。

  3. If you needed to have getter and setter functions, perhaps to check something, in Python you can declare special method functions.如果你需要 getter 和 setter 函数,也许是为了检查一些东西,在 Python 中你可以声明特殊的方法函数。 This is what Martin v. Löwis meant when he said "property descriptors".这就是 Martin v. Löwis 所说的“财产描述词”的意思。 In Python, it is generally considered good practice to simply assign to member variables, and simply reference them to fetch them, because you can always add in the property descriptors later should you need them.在 Python 中,简单地分配给成员变量,然后简单地引用它们来获取它们,通常被认为是一种很好的做法,因为如果您需要它们,您可以随时添加属性描述符。 (And if you never need them, then your code is less cluttered and took you less time to write. Bonus!) (如果您永远不需要它们,那么您的代码就不会那么杂乱,并且花费的时间也更少。奖金!)

Here's a good link about property descriptors: http://adam.gomaa.us/blog/2008/aug/11/the-python-property-builtin/这是关于属性描述符的一个很好的链接: http : //adam.gomaa.us/blog/2008/aug/11/the-python-property-builtin/

Note: Adam Gomaa's blog seems to have disappeared from the web.注意:Adam Gomaa 的博客似乎从网络上消失了。 Here's a link to a saved copy at archive.org:这是在 archive.org 上保存的副本的链接:

https://web.archive.org/web/20160407103752/http://adam.gomaa.us/blog/2008/aug/11/the-python-property-builtin/ https://web.archive.org/web/20160407103752/http://adam.gomaa.us/blog/2008/aug/11/the-python-property-builtin/

  1. It doesn't really matter if you specify values as part of the call to Team() or if you poke them into your class instance later.如果您将值指定为Team()调用的一部分,或者您稍后将它们插入类实例中,这并不重要。 The final class instance you end up with will be identical.您最终得到的最终类实例将是相同的。
team = Team("Joe", "http://example.com", 1)
team2 = Team()
team2.name = "Joe"
team2.logo = "http://example.com"
team2.members = 1

print(team.__dict__ == team2.__dict__)

The above will print True .以上将打印True (You can easily overload the == operator for Team instances, and make Python do the right thing when you say team == team2 , but this doesn't happen by default.) (您可以轻松地为Team实例重载==运算符,并在您说team == team2时让 Python 做正确的事情,但默认情况下不会发生这种情况。)


I left out one thing in the above answer.我在上面的答案中遗漏了一件事。 If you do the optional argument thing on the __init__() function, you need to be careful if you want to provide a "mutable" as an optional argument.如果你在__init__()函数上做可选参数的事情,如果你想提供一个“可变”作为可选参数,你需要小心。

Integers and strings are "immutable".整数和字符串是“不可变的”。 You can never change them in place;你永远不能就地改变它们; what happens instead is Python creates a new object and replaces the one you had before.相反,Python 会创建一个新对象并替换您之前拥有的对象。

Lists and dictionaries are "mutable".列表和字典是“可变的”。 You can keep the same object around forever, adding to it and deleting from it.您可以永远保留同一个对象,向其中添加或从中删除。

x = 3   # The name "x" is bound to an integer object with value 3
x += 1  # The name "x" is rebound to a different integer object with value 4

x = []  # The name "x" is bound to an empty list object
x.append(1)  # The 1 is appended to the same list x already had

The key thing you need to know: optional arguments are evaluated only once, when the function is compiled.您需要知道的关键是:在编译函数时,可选参数只计算一次。 So if you pass a mutable as an optional argument in the __init__() for your class, then each instance of your class shares one mutable object.因此,如果您在类的__init__()中将可变参数作为可选参数传递,那么您的类的每个实例共享一个可变对象。 This is almost never what you want.这几乎永远不是您想要的。

class K(object):
    def __init__(self, lst=[]):
        self.lst = lst

k0 = K()
k1 = K()

k0.lst.append(1)

print(k0.lst)  # prints "[1]"
print(k1.lst)  # also prints "[1]"

k1.lst.append(2)

print(k0.lst)  # prints "[1, 2]"

The solution is very simple:解决方法很简单:

class K(object):
    def __init__(self, lst=None):
        if lst is None:
            self.lst = []  # Bind lst with a new, empty list
        else:
            self.lst = lst # Bind lst with the provided list

k0 = K()
k1 = K()

k0.lst.append(1)

print(k0.lst)  # prints "[1]"
print(k1.lst)  # prints "[]"

This business of using a default argument value of None , then testing that the argument passed is None , qualifies as a Python design pattern, or at least an idiom you should master.这种使用默认参数值None ,然后测试传递的参数is None ,符合 Python 设计模式,或者至少是您应该掌握的习语。

class Team:
  def __init__(self):
    self.name = None
    self.logo = None
    self.members = 0

In Python, you typically don't write getters and setters, unless you really have a non-trivial implementation for them (at which point you use property descriptors).在 Python 中,您通常不会编写 getter 和 setter,除非您确实对它们有一个重要的实现(此时您使用属性描述符)。

To write classes you would normally do:要编写类,您通常会执行以下操作:

class Person:
    def __init__(self, name, age, height):
        self.name = name
        self.age = age
        self.height = height

To instantiate instances of a class(es) you would do要实例化一个类的实例,你会这样做

person1 = Person("Oscar", 40, "6ft")

person2 = Team("Danny", 12, "5.2ft")

You can also set a default value:您还可以设置默认值:

 class Person:
        def __init__(self):
            self.name = "Daphne"
            self.age = 20
            self.height = "5.4ft"

To instantiate a classes set like this, you want to do:要实例化这样的类集,您需要执行以下操作:

person3 = Person()
person3.name = "Joe"
person3.age = 23
person3.height = "5.11ft"

You will notice that this method bears a lot of similarity to your typical Python dictionary interaction.您会注意到此方法与您典型的 Python 字典交互有很多相似之处。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM