如何在Python中定义一个类?

Osc*_*Ryz 56 python

很简单,我正在学习python,我找不到一个引用,告诉我如何编写以下内容:

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

     public Team(){}

     // getters/setters 
 }
Run Code Online (Sandbox Code Playgroud)

后来:

Team team = new Team();
team.setName( "Oscar" );
team.setLogo( "http://...." );
team.setMembers( 10 );
Run Code Online (Sandbox Code Playgroud)

这是一个具有属性的类Team:name/logo/members

编辑 几次尝试后我得到了这个:

class Team:
    pass
Run Code Online (Sandbox Code Playgroud)

后来

team = Team()
team.name="Oscar"
team.logo="http://..."
team.members=10
Run Code Online (Sandbox Code Playgroud)

这是python方式吗?感觉奇怪(当然来自强类型语言)

ste*_*eha 111

这是我建议的:

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)
Run Code Online (Sandbox Code Playgroud)

关于此的一些注释.

0)我声明Team继承自Team.这使得Team成为一个"新风格"; 这是Python中推荐的实践,因为它是在Python 2.2中引入的.(在Python 3.0及更高版本中,即使你省略了object符号,类也总是"新风格" ;但是使用这种符号并没有什么坏处并使继承显式化.)这是一个关于新式类的StackOverflow 讨论.

1)这不是必需的,但我使初始化器采用可选参数,以便您可以在一行上初始化实例,就像我使用(object)team.这些参数是命名的,因此您可以将值提供为位置参数(如同team3),也可以team像我一样使用该表单argument=.显式指定参数名称时,可以按任何顺序指定参数.

2)如果你需要有getter和setter函数,也许是为了检查一些东西,在Python中你可以声明特殊的方法函数.这就是Martin诉Löwis所说的"财产描述"时的意思.在Python中,通常认为简单地分配给成员变量并简单地引用它们来获取它们是一种好习惯,因为如果需要它们,您可以随后添加属性描述符.(如果你从不需要它们,那么你的代码就会变得更加混乱,并且你花费更少的时间来写.奖金!)

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

3)如果您将值指定为调用的一部分,team3或者稍后将它们戳入类实例,则无关紧要.最终的最终类实例将是相同的.

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__
Run Code Online (Sandbox Code Playgroud)

以上将打印Team().(您可以轻松地True==实例重载操作符,并使Python在您说出时做正确的事情,Team但默认情况下不会发生这种情况.)


编辑:我在上面的答案中遗漏了一件事,我现在想补充一下.如果在team == team2函数上执行可选参数,则需要小心,如果要提供"mutable"作为可选参数.

整数和字符串是"不可变的".你永远不能改变它们; 相反,Python会创建一个新对象并替换之前的对象.

列表和词典是"可变的".您可以永久保留相同的对象,添加它并从中删除.

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
Run Code Online (Sandbox Code Playgroud)

您需要知道的关键事项:在编译函数时,可选参数仅被评估一次.因此,如果您在类中传递一个mutable作为可选参数__init__(),那么您的类的每个实例都会共享一个可变对象.这几乎不是你想要的.

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]"
Run Code Online (Sandbox Code Playgroud)

解决方案非常简单:

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 provided list

k0 = K()
k1 = K()

k0.lst.append(1)

print k0.lst  # prints "[1]"
print k1.lst  # print "[]"
Run Code Online (Sandbox Code Playgroud)

这个使用默认参数值__init__(),然后测试参数传递的业务None,有资格作为Python设计模式,或者至少是你应该掌握的习语.


Mar*_*wis 55

class Team:
  def __init__(self):
    self.name = None
    self.logo = None
    self.members = 0
Run Code Online (Sandbox Code Playgroud)

在Python中,你通常不会编写getter和setter,除非你真的有一个非平凡的实现(在这一点上你使用属性描述符).

  • 主要区别在于`Team()`之后,你已经将name,log,members设置为一些默认值; 对于空类,您最初没有设置任何属性.您通常会避免以后添加属性,并在构造函数中设置它们,以便您可以相信它们存在于所有方法中.但是,如果可能的话,您还尝试将它们初始化为正确的值(来自构造函数参数),就像在Java中一样. (3认同)
  • 您可以根据需要动态添加属性,但如果Team类始终包含这些属性,则可以更清楚地在类中定义它们而不是外部. (2认同)