01/10/2018, 09:45

Python self trong Class

Chào cả nhà , em vừa mới học python chừng 2 tuần,về đụng đến phần Class trong python, em đã đọc qua OOP là gì và cũng khá hiểu vài cái ví dụ như Constructor hoặc Method của class ,nhưng thật sự em vẫn không biết từ khóa “self” để làm gì , tại sao phải buộc có nó , và sử dụng như thế nào cho đúng ,dưới đây là đoạn code em mượn của bạn để hỏi cho tiện ạ:


class Trigger(object):
    """Base class for all triggers"""

    def __init__(self, x, y, z, block_type, block_data=0, one_time=True):
        # set values
        self.pos = Vec3(x, y, z)
        self.block = Block(block_type, block_data)
        self.one_time = one_time

        # add self to triggers list
        triggers.append(self)


class TriggerStepOn(Trigger):
    """Base class for blocks that trigger an event when it is step on"""

    def __init__(self, x, y, z, block_type, block_data=0, one_time=True):
        Trigger.__init__(self, x, y + 1, z, block_type, block_data, one_time)

        # set block under trigger block to correct type
        mc.setBlock(x, y, z, self.block)

    def condition(self):
        """check if hansel steps on block"""
        if self.pos == tilePos:
            return True
        return False
Henry viết 11:58 ngày 01/10/2018

mình có một số bài viết về python oop. Tuy chưa hết nhưng đã có nói qua về self. Bạn tham khảo https://medium.com/graktung/series-python-oop-tập-1-class-and-instances-1fd17f499055

Thành Long viết 11:49 ngày 01/10/2018

Dạ mình cảm ơn , mình sẽ đọc ngay
Mọi người nhớ để lại cho em một vài ví dụ dễ hiểu về cách sư dụng self ,em cảm ơn rất nhiều

Thành Long viết 11:51 ngày 01/10/2018

Cảm ơn bạn mình hiểu self rồi ,nhưng lại thắc mắc về cách tạo Class con thừa kế , và việc gọi constructor của Class con hoặcviệc gọi constructor của Class cha trong class hoặc việc gọi cả constructor của cha và con trong Class con ảnh hưởng như nào.Mình tìm trong bài viết không thấy

Henry viết 11:55 ngày 01/10/2018

Dạo này mình bận quá nên chưa viết thêm được.

Thân Hoàng viết 11:49 ngày 01/10/2018

Bác xóa bài bao giờ thế T.T

Henry viết 11:52 ngày 01/10/2018

Cũng lâu rồi

Thân Hoàng viết 12:00 ngày 01/10/2018

còn link không bác, cho em với. Đang hoang mang quá

Henry viết 11:53 ngày 01/10/2018

Bạn đang tìm hiểu Python OOP?

Thân Hoàng viết 11:53 ngày 01/10/2018

vâng. càng học càng rối như tơ vò

Henry viết 11:54 ngày 01/10/2018

Bữa trước mình mới thấy bạn tìm hiểu C, C++ mà sao giờ đã tới Python OOP rồi vậy? Bạn nói rõ xem rối chỗ nào? mình rảnh sẽ viết cho bạn hiểu

Thân Hoàng viết 11:46 ngày 01/10/2018

em đang học Python.
C em học từ thời gian trước rồi, không sâu lắm. Hôm trước thằng bạn nó hỏi bài em, em thì cũng lơ mơ phần đấy nên hỏi thôi ^^

Thân Hoàng viết 11:52 ngày 01/10/2018

Em có một số câu hỏi:

  • Các hàm bên trong một class, luôn có tham số self, self là bắt buộc của cú pháp hay chỉ là tên mà người ta quy ước với nhau.
  • Class abc(object): kế thừa lớp object, vậy cái class object nó ở chỗ nào và nó có những phương thức nào ạ ?.
    -Anh có thể giả thích kĩ hơn cách mà hàm__init__ hoạt động giúp em được không ạ Em được biết nó là hàm này sẽ được chạy đầu tiên khi tạo một đối tượng. Các biến trong nó có phải là biến cục bộ của cả class ?2
Henry viết 11:47 ngày 01/10/2018

1.Các hàm bên trong một class, luôn có tham số self, self là bắt buộc của cú pháp hay chỉ là tên mà người ta quy ước với nhau

self là đại diện cho instance. Hãy xem ví dụ sau đây

class A:
    def wazzup():   # method không có parameter self
        print("Wazzupppp!")

Mình sẽ cho bạn thấy sự khác biệt giữa có self và không có self

>>> A.wazzup()       # kết quả dễ đoán
Wazzupppp!
>>> ob = A()           # tạo một đối tượng, đối tượng này là instance của lớp A
>>> ob.wazzup()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: wazzup() takes 0 positional arguments but 1 was given

Bạn thấy chứ, wazzup() takes 0 positional arguments but 1 was given. Rõ ràng ta không truyền bất cứ argument nào nhưng nó lại báo là đã truyền 1. Sự thật là mình đã truyền một argument là đối tượng ob. Và đương nhiên chúng ta cần một parameter trong phương thức để nhận lấy giá trị đó. Và người ta quy ước dùng self. Vì sao là quy ước? Bởi vì nó chỉ là parameter thôi, bạn hoàn toàn có thể thay thế những chữ cái khác nếu bạn thích. Theo mình biết là như thế, tại mình từng vọc và thay thế self bằng chữ trời ơi đất hỡi khác và vẫn được.

2.Class abc(object): kế thừa lớp object, vậy cái class object nó ở chỗ nào và nó có những phương thức nào ạ

Thật ra thì text editor nó in ra thế thôi chứ làm gì có object nào . Nó giống như việc nó gõ dùm bạn syntax sẵn thôi.

3.Anh có thể giả thích kĩ hơn cách mà hàm__init__ hoạt động giúp em được không ạ.

Cái phương thức này đặc biệt ở chỗ nó sẽ tự động được invoke (gọi) khi khởi tạo đối tượng. Cũng còn một cái method nữa cũng sẽ được invoke nhưng cũng chả nhớ lắm vì nó không quan trọng. Nó giống như là một cái setup dùm attribute cho đói tượng dùm mình. Lấy ví dụ đơn giản không dùng __init__

class A:
    pass   # không có ý nghĩa gì đâu
>>> ob = A()   # ob là một đối tượng của lớp A
>>> ob.name = "object"     # khởi tạo một attribute tên name, giá trị "object"
>>> ob.age = 16               # khởi tạo một attribute tên age, giá trị 16
>>> ob.level = 200            # khởi tạo một attribute tên level, giá trị 200
>>> ob.name        # và nó cũng giống như biến
"object"
>>> ob.age, ob.level
(16, 200)

Đặt vấn đề, bạn phải khai báo 100 đối tượng (không dùng loop - vòng lặp) thì bạn phải mất 1 dòng khởi tạo đối tương, 3 dòng khởi tạo các attribute tổng cộng là 4 dòng 1 đối tượng => 400 dòng 100 đối tượng. Ta hãy than khảo phương thức __init__ nhé

class A:
    def __init__(self, p_name, p_age, p_level):
        self.name  = p_name
        self.age   = p_age
        self.level = p_level 

Ta sẻ khởi tạo đối tượng, nhớ là thêm cho đủ 4 argument

>>> ob = A("object", 16, 200)   # self là ob, "object" là p_name, 16 là p_age còn 200 là p_level

Và hãy thay thế những thứ mới đề cập đi nào

def __init__(self, p_name, p_age, p_level):
    self.name  = p_name
    self.age   = p_age
    self.level = p_level 

Sẽ được biến hóa thành

def __init__(ob, "object", 16, 200):
    ob.name  = "object"
    ob.age   = 16
    ob.level = 200 

Vậy ta chỉ cần 100 dòng cho 100 đối tượng. + 4 dòng cho phương thức __init__ là 104
Không những thế, bạn còn tránh sai sót khi khởi tạo thiếu attribute mà bạn không hề biết.

Thân Hoàng viết 11:51 ngày 01/10/2018

Em cảm ơn anh nhiều. Vẫn còn hơi mông lung nhưng em cũng hiểu được 80-90% những gì anh nói r ạ :))

Henry viết 11:59 ngày 01/10/2018

Ai gặp hướng đối tượng thì cũng hơi khó hiểu ban đầu. Nếu em biết ai mà hiểu ngay từ lần đầu tiên thì nói cho anh biết nhé

Thân Hoàng viết 12:01 ngày 01/10/2018

Chắc chỉ có ông nghĩ ra cái gọi là OOP thì mới hiểu luôn anh ạ :))

Bài liên quan
0