The use of self in multiple methods of a class
所以,作为一个初学者,我创建了这个程序,它使用tkinter来计算pokemon-go中不同pokemon/candy组合的最大可能演变。我先创建了这个程序,然后才对代码使用函数。然而,我认为使用一门课会很好,经过一些研究,这就是结果。但是,我基本上是通过在不同方法的一大堆变量中添加self来实现的。
我的问题是:在这里使用一个类是否相关?我对类的研究涉及到用对象等填充一个类,但这里我只创建一个对象,以便使用该类并运行一系列计算。
此外,如何知道调用变量时何时使用self。例如,我创建静态类变量的感觉是,我不需要将实例本身放在它前面就可以使用它,但是这不起作用,所以我只是在调用变量之前放置了更多的自我。为什么把一堆自我放在每件事情的前面?自我是不是太过分了,我能用更聪明的方式去做吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | from tkinter import * from tkinter import messagebox class PokeCalculator(Frame): pokedex = { 'pidgey': 12, 'caterpie': 12, 'weedle': 12, 'rattata': 25 } choices = pokedex.keys() screen_title = 'Pokemon evolve calculator' def __init__(self, master=None): Frame.__init__(self, master) self.master = master self.make_window() def make_window(self): self.master.title(self.screen_title) L1 = Label(self, text='Candies') L1.grid(column=1, row=0) L2 = Label(self, text='Pokemon amount in storage') L2.grid(column=2, row=0) self.var = StringVar() self.var.set('Pokemon') self.Pokemon = OptionMenu(self, self.var, *self.choices) self.Pokemon.grid(column=0, row=1) self.Candies = Entry(self) self.Candies.grid(column=1, row=1) self.Poke_amount = Entry(self) self.Poke_amount.grid(column=2, row=1) Calculate = Button(self, text='Calculate', command=self.get_and_check) Calculate.grid(column=1, row=2) def get_and_check(self): self.get_values() self.check_input() def get_values(self): self.poke = self.var.get() self.candies_total = self.Candies.get() self.p_amount = self.Poke_amount.get() def check_input(self): string1 = 'Please select a Pokemon from the dropdown menu' string2 = 'Please only enter numbers' if self.poke == 'Pokemon': messagebox.showinfo(self.screen_title, string1) elif not self.p_amount.isdigit() or not self.candies_total.isdigit(): messagebox.showinfo(self.screen_title, string2) else: self.too_few_pokemon() def too_few_pokemon(self): candies_total = int(self.candies_total) p_amount = int(self.p_amount) evolve = int((candies_total - 1) / (self.pokedex[self.poke] - 1)) candies_needed = (p_amount * (self.pokedex[self.poke] - 1)) + 1 if p_amount <= evolve: n = 0 while candies_needed <= candies_total: n = n + 1 p_amount = p_amount + 1 candies_needed = ((p_amount) * (self.pokedex[self.poke] - 1)) + 1 candies_total = candies_total + 3 evolve2 = int((candies_total - 1) / (self.pokedex[self.poke] - 1)) string1 = ''' You have enough candies too evolve {0} {1}, but you only have {2} {1} in storage and thus can only evolve {2} {1}. If you catch {3} more {1} you can now evolve {4} {1}.''' messagebox.showinfo(self.screen_title, string1.format(evolve, self.poke, self.p_amount, n, evolve2)) else: self.too_much_pokemon() def too_much_pokemon(self): candies_total = int(self.candies_total) p_amount = int(self.p_amount) candies_needed = (p_amount * (self.pokedex[self.poke] - 1)) + 1 m = 0 while candies_total <= candies_needed: m = m + 1 p_amount = p_amount - 1 candies_needed = ((p_amount) * (self.pokedex[self.poke] - 1)) + 1 candies_total = candies_total + 1 evolve = int((candies_total - 1) / (self.pokedex[self.poke] - 1)) string2 = 'Transfer {0} {1} so you can evolve a total of {2} {1}.' messagebox.showinfo(self.screen_title, string2.format(m, self.poke, evolve)) root = Tk() app = PokeCalculator(root) app.pack() root.mainloop() |
第一次-课堂的使用在这里也很重要。几乎Python中的所有内容都是一个对象,即使您没有意识到它。第二,类变量和实例变量之间存在差异。把课堂想象成一个蓝图。每次希望基于类创建对象时,都会访问此蓝图。在类内部声明的变量,但在任何方法(例如pokedex)外部声明的变量称为类变量。它们保存了蓝图的值。创建类(对象)的实例时,这些类变量将转换为对象的实例变量。实例变量是在init和其他函数中定义的,您可以使用self.variable引用任何实例变量。关于类和实例有很多要了解的地方,它不能在一个简单的堆栈溢出答案中进行编译。遵循https://docs.python.org/3.6/tutorial/classes.html
看看你的代码,你做得很好。我会使用更多的"self":)例如在l1、l2或calculate上,因为我不知道什么时候要在创建它们的方法之外引用它们。很好的规则是,在类中使用self以后可能需要的任何东西:)
最后但并非最不重要:是的,您的程序可能没有任何自定义类。或者,您不需要使用类或实例变量,而是将所有内容保存在全局和局部变量中。它也可以不使用任何方法或函数:)并且可以用汇编语言编写:d有很多可能性,但是当您进行面向对象的编程时,使用对象很好:)现在您的类是可重用的,例如,我可以将它从模块导入到我的程序中。:)即使每个程序只实例化一个类中的一个对象,通常也使用类作为它的蓝图。更容易理解整个代码及其部分。就像在现实世界中——我是彼得,我是一个典型的阶级人物。我有一只右手,我称之为"我自己"。右手(我的右手,不只是任何一只手),这只手是"班级之手"的一个例子。类手有一个方法抓取。我的右手也能抓住!我用右手抓住一个苹果,叫自己。右手。抓住(苹果)。
祝你前进顺利!
请考虑以下示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 | class A: a_class_attribute = 'A class attribute' def __init__(self, a): self.a_instance_attribute = a def amethod(self): print('a method') class B(A): b_class_attribute = 'B class attribute' def __init__(self, b): self.b_instance_attribute = b def bmethod(self): print('b method') |
现在,我们来举一个
1 | In [2]: a = A('foo') |
注意,通过检查实例的
1 2 | In [3]: a.__dict__ Out[3]: {'a_instance_attribute': 'foo'} |
这是有意义的,因为我们有一个实例属性。那班呢?
1 2 3 4 5 6 7 8 9 | In [7]: A.__dict__ Out[7]: mappingproxy({'__dict__': , '__doc__': None, '__init__': <function self_oop_ex.A.__init__>, '__module__': 'self_oop_ex', '__weakref__': , 'a_class_attribute': 'A class attribute', 'amethod': <function self_oop_ex.A.amethod>}) |
所以
1 2 3 4 5 | In [8]: A.a_class_attribute Out[8]: 'A class attribute' In [9]: a.a_class_attribute Out[9]: 'A class attribute' |
现在,这和
1 2 | In [10]: a.amethod() a method |
相当于:
1 2 | In [11]: A.amethod(a) a method |
方法就是这样!与其他任何函数一样,如果函数是从实例中获得的,那么python通过隐式传递实例来帮助我们。注意,我们可以这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | In [17]: class Krazy: ...: def use_pop(self): ...: return self.pop() ...: def pop(self): ...: print("I am a Krazy pop") ...: In [18]: k = Krazy() In [19]: k.pop() I am a Krazy pop In [20]: mylist = [1,2,3,4,5] In [21]: mylist.pop() Out[21]: 5 In [22]: k.use_pop() I am a Krazy pop In [23]: Krazy.use_pop(mylist) Out[23]: 4 |
注:
最后,考虑类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | In [25]: b = B('bar') In [26]: b.__dict__ Out[26]: {'b_instance_attribute': 'bar'} In [27]: B.__dict__ Out[27]: mappingproxy({'__doc__': None, '__init__': <function self_oop_ex.B.__init__>, '__module__': 'self_oop_ex', 'b_class_attribute': 'B class attribute', 'bmethod': <function self_oop_ex.B.bmethod>}) In [28]: b.amethod() a method In [29]: b.bmethod() b method In [30]: b.a_class_attribute Out[30]: 'A class attribute' In [31]: b.b_class_attribute Out[31]: 'B class attribute' |
当然,多重继承会变得更加复杂,但是现在,试着担心简单的继承情况。
https://docs.python.org/2/tutorial/classes.html类和实例变量
实例属性特定于类的实例(对象)。类属性与类有关。这些属性由类的所有实例共享。
在代码中,
在这里使用一个类甚至是相关的吗?
我会说是的。类是数据和方法的逻辑分组。它封装了一些数据和一些可以对这些数据执行的方法。我们不只是把随机的东西放在一个类中,而是尝试在事物之间有逻辑连接的地方创建类。
这可能是一个有用的来源:https://jeffknupp.com/blog/2014/06/18/improve-your-python-python-classes-and-object-oriented-programming/