Python でオブジェクト指向プログラミングを書きたいと知ったとき、私はためらって落ち着きませんでした。この穴をどうやって登ればいいのかと考えていました。 Pythonはオブジェクト指向の内容が多いので、しっかり解説したい場合は、前回の内容をオブジェクト指向の考え方で学び直すのがベストです。この穴はとても大きいので、迷った末に重要な内容だけを取り上げましょう。足りない内容は皆で補うしかありません。
規約として、私が使用しているバージョンは python2.7 であり、バージョンごとに違いがある可能性があります。
それでは、始める前に、質問について考えてコードを見てみましょう:
a の値を作成するだけで、自分が書いていないメソッドを使用できるのはなぜですか?
友人の中には、「この時点では a は文字列オブジェクトなので、当然、文字列メソッドを使用できます。これらのメソッドは Python によって事前に記述されています。」と言う人もいるかもしれません。
さて、質問を変えましょう。なぜ Python はそれが文字列オブジェクトであることを認識するのでしょうか?
この問題について詳しく説明する前に、一文を思い出してください。Python のすべてはオブジェクトであり、オブジェクトはクラスによって作成されます。
では、クラスとは何でしょうか?ここで例を示します。
ある日、道を歩いていると、突然目の前に敵が現れました。この時、私は彼を殴りたかったが、力が相互作用し、彼を殴ると拳が痛くなるだろう。おい、このとき道端に石を見つけたんだ、大きさも形もちょうどよかった、警察官がどう思ったかはともかく、これはいい選択だった。それから私は石を拾い上げ、良い子には真似できないような行動を敵に対して行いました。それから私は自分の功績と名声を隠し、これをやめて家に帰りました。
この過程で、なぜそれが石であることがわかるのでしょうか?
見た目が石だから!
なぜ石が人に当たる可能性があることがわかっているのでしょうか?
石が硬いから!
なぜ岩が硬いことがわかるのでしょうか?
だって…そうですね…私が小さかった頃、父が私にこう言ったんです。
この時点で結論を導き出すことができます。つまり、私たちはその物が何であるか、そしてそれがどのような機能を持っているかを知っています。なぜなら、私たちはすでにその物の概念を頭の中に持っているからです。この概念は長老から知られている場合もあれば、さまざまな実験を経て自分でまとめたものである場合もあります。 「ブラックホール」についての私たちの理解と同様に、それらは科学者によるさまざまな研究から導き出されています。
誰かを石で殴る例をコードに実装する方法:
class Stone(object): # 我创建一个叫Stone的类 def attack(self): print '把头伸过来,我给你加个buff' a = Stone() # 我用类创建了一个对象,也称为类的实例化 a.attack() # 我使用这个对象的方法
素晴らしい、それが私たちが必要としていたものです。
他のオブジェクトを作成する場合:
明らかに、Python は攻撃方法を用意していないため、使用できません。
いわゆるクラスは単なる抽象定義ですが、インスタンスは具体的なオブジェクトです。それらの違いは私の心の中の石と手の中の石のようなもので、後者だけが現実です。もちろん、ここでは理想論などについて話さないでください。
これを見ると、クラスとオブジェクトの関係がより明確になるはずです。一部の学生は、「Python のすべてのクラスは事前に作成されています。Python にクラスを自動的に生成させ、特定のタイミングでこれらのクラスを使用させる方法はありますか?」と尋ねるかもしれません。おめでとうございます、クラスメート、あなたは人工知能の限界に達したかもしれません。それが実現できれば、それは私たちの学習能力と同じになるのではないでしょうか。まあ、これは私の単なるアイデアですが、実際の人工知能を実現する方法はまだわかりません。しかし、プログラマーとしては、人工知能をプログラミングできるようになるかもしれません。さあ、生涯の追求です。
クラスとインスタンス化とは何かについて説明した後、クラスの基本的な構文を見てみましょう。
まず、classは関数を定義するdefと同様にクラスを定義するためのキーワードです。
以下はクラス名であり、同様に、Python の組み込みキーワードと競合することはできません。さらに、Python の組み込み型 (str や int などの名前) は避けることをお勧めします。標準的な命名は、「キャメルケース命名方法」に従う必要があります。例: MyClass ここでの命名では、各単語の最初の文字が大文字になります。
次に括弧があり、内部のパラメータは継承用であり、通常はオブジェクトから継承され、新しいスタイル クラスを示します。また、古典的な書き方である括弧なしで書かれているのを見たことがあるかもしれません。
示例:
class NewClass(object): pass class OldClass: pass New = NewClass() # 创建一个新式类的实例 Old = OldClass() # 创建一个经典类的实例
这就是类的基本语法,当然这样还是不够的,但是在更深入之前,我想先讲一个新旧式类的差别。
在这里,我们先打印一下两个变量的类型:
print type(New) print type(Old)
可以看下两者的输出是不同的。
在早于python2.2的版本时,只有经典类这一种写法,当时,类和类型没有合并。
类是类对象,实例是实例对象,这两个对象之间没有任何关系。
这句话是什么意思?看代码:
print type(OldClass) print type(Old)
我们可以看见其输出很含糊,经典类属于类对象,无论是哪个类,都统一为“类”类型,实例属于实例类型,却不知道其是由哪个类创建的,所以的实例都统一为“实例”类型。也就是说当时的类型用 classobj 和 instance 代表了所以的类和实例,无论你是哪个类,又或是哪个类创建的实例。
这样的信息实在太少,而类和类型之间非常混乱。为了解决这种情况,在 python2.2 中引入了新式类,并进行了类和类型的同统一。
print type(NewClass) print type(New)
类的类型是 type?type 返回的对象还能像类一样创新新对象?
总结的来说:在新式类中,所以的类对象都是 type 的实例。而不同的类对象有能创建出其对应的实例。
class NewClass(object): def __init__(self, val): self.val = val New = NewClass(123) b = type(New)(321) # 对实例来说type返回的是类对象,我又可以用类对象来和创建新的实例 print b.val
构造器方法
一般可以理解类中的函数就是方法,而方法分为:实例方法,只有实例化后才能调用的,其第一个参数一般为 self,代表实例本身;类方法,其第一个参数为 cls,代表类本身;还有静态方法,就是个普通函数,没有要求参数。
1. __init__(self [,arg1,....]):
当类被调用进行实例化的时候,python会自动调用类里面的构造函数(如果有的话),在构造函数中,可以进行各种初始化的操作,最常见的就是上面的进行实例的属性的创建。
python 在示例化的时候,会检查其实行了 __init__ 方法了没有,如果没有则不对实例进行任何操作,然后返回对象。如果实行了这个方法,则自动调用这个方法,并自动将 self 传进行,也就是说我们在实例化进行传参的时候,将不用理会 self,直接传给后面的参数。
讲到属性,就必须要提一下什么是属性。属性这个对象其实更像一个变量,大多数对象都可以有属性(不包括python的内置类型),例如函数。
def Test(): pass Test.a = 123 print Test.a
因为函数也是一个对象。
属性在类中,就是一个变量,例如:
class NewClass(object): a = 123 print NewClass.a
当然,因为 python 的特性,我们可以在运作中为某个对象添加属性,而不用一开始就在类中写定。
注意,这个方法应该返回 None,也就是说我们一般不用 return 任何对象,让它默认返回就行了。
2. __new__(cls [,arg1,....]):
这也是一个构造器方法,它是一个类方法,一般在对 python 的不可变数据类型进行继承扩展的时候用的比较多。
某处拿来的代码示例:
class RoundFloat(float): def __new__(cls, val): return super(RoundFloat, cls).__new__(cls, round(val, 2)) a = RoundFloat(3.14159) print a
解构器方法
__del__(self [,arg1,....])
这个方法将会在对象所以的引用被清除后才执行,例如:
class Test(object): def __del__(self): print '我被干掉了,兄弟们为我报仇!' a = Test() # 创建了一个对象 b = a # b又引用了a c = b # c又引用了b,现在 a 所指向的对象有3次引用,相当有三条命 del a # 干掉一条命 del b # 又干掉 del c # 听说你有3条命?全部干掉!
注意,这里只输出了一次,也就是说到了最后才删除完毕。这里要注意一下几点:
1. del の呼び出しはオブジェクトの削除が完了したことを意味するものではなく、参照が減少するだけです。
2. 循環参照またはインスタンスへの参照が残るその他の理由がある場合、オブジェクトの __del__() が実行されない可能性があります。
3. __del__() でキャッチされなかった例外は無視されます (__del__() で使用される一部の変数が削除されている可能性があるため)。 __del__() では、インスタンスと関係のないことは行わないでください。
4. 通常、この方法には一定のリスクが伴うため、実装する必要はありません。
5. __del__ を定義し、インスタンスがループの一部である場合、ガベージ コレクターはループを終了しません。明示的に del を自分で呼び出す必要があります。
6. 親クラスを継承し、その親クラスにデストラクターがある場合は、それを忘れずに呼び出してください。そうしないと、親クラスの一部のクリーニング メソッドが呼び出されず、次の予期しないエラーが発生する可能性があります。
Python のオブジェクト指向とクラスの基本構文について簡単に説明した上記の記事は、エディターが共有したすべての内容です。参考にしていただければ幸いです。また、皆様にも Script Home をサポートしていただければ幸いです。