Computer >> Máy Tính >  >> Lập trình >> Python

Lập trình meta với Metaclasses trong Python


Thuật ngữ siêu lập trình đề cập đến lập trình máy tính trong đó các chương trình máy tính cố gắng thao tác hoặc có kiến ​​thức về chính nó. Python hỗ trợ lập trình siêu ứng dụng cho các lớp thông qua một loại lớp mới được gọi là siêu kính.

Lập trình meta thông qua metaclasses trong python là xây dựng các hàm và lớp thao tác mã bằng cách sửa đổi, gói hoặc tạo mã hiện có.

Các tính năng chính của lập trình meta là -

  • Kính đeo tay
  • Người trang trí
  • Người trang trí lớp học

Metaclass là gì

Một định nghĩa rất hạn chế về metaclass có thể là, một lớp tạo ra một lớp. Python là một ngôn ngữ hướng đối tượng mà mọi thứ đều là một đối tượng và các lớp cũng không ngoại lệ. Định nghĩa một lớp với từ khóa lớp, python thực sự thực thi nó và sau đó tạo một đối tượng. Vì nó là một đối tượng, bạn có thể gán, sao chép, thêm thuộc tính, làm tham số hàm, v.v. Sử dụng metaclasses cho phép chúng tôi kiểm soát việc tạo ra các lớp, chẳng hạn như sửa đổi các thuộc tính của một lớp, kiểm tra tính hợp pháp của thuộc tính, v.v.

Metaclass tích hợp sẵn trong Python

Metaclass của tất cả các lớp là loại

class a:
pass

print(type(a))

Đầu ra:

<class 'type'>

Từ kết quả trên, chúng ta có thể thấy rằng “a” (class) là một đối tượng của kiểu lớp. Chúng ta cũng có thể nói rằng “a” (lớp) là một thể hiện của kiểu lớp. Vì vậy, loại là một siêu thủy tinh. Vì vậy, trong python, mọi lớp đều thuộc loại siêu kính tích hợp.

Lập trình meta với Metaclasses trong Python

Sử dụng Metaclass để tạo một lớp python

Như chúng ta đã thấy trong ví dụ trên, loại là siêu kính mặc định. Chúng tôi có thể tạo một lớp mới với sự trợ giúp của (loại) siêu kính mặc định này.

>>> class hello(object):
pass

cũng có thể được tạo thủ công theo cách này -

>>> hello = type('hello', (), {})
>>> print(hello)# returns a class object

>>> print(hello()) # creates an instance with the class
<__main__.hello object at 0x05D86830>

Type chấp nhận một từ điển để xác định các thuộc tính của lớp, vì vậy

>>> class hello(object):
   world = True

Đoạn mã trên tương tự như,

hello = type('hello', (), {'world' : True})

Tạo siêu kính

Vậy tạo metaclass khi nào? Khi tôi muốn kiểm soát việc tạo một lớp, chẳng hạn như xác minh hoặc sửa đổi các thuộc tính của một lớp.

Quá trình khởi tạo của lớp -

  • Tạo một phiên bản bằng cách gọi __new __ ()
  • Gọi __init __ () để khởi tạo phiên bản đã tạo ở trên

Vì vậy, khi chúng tôi tạo siêu kính tùy chỉnh, chúng tôi thực sự thay đổi phương thức __new __ () hoặc __init__ của lớp cha.

Ví dụ1 - Metaclass đã sửa đổi các thuộc tính của lớp

class LowercaseMeta(type):
   def __new__(mcs, name, bases, attrs):
      lower_attrs = {}
      for k, v in attrs.items():
         if not k.startswith('__'):
            lower_attrs[k.lower()] = v
         else:
            lower_attrs[k] = v
      return type.__new__(mcs, name, bases, lower_attrs)
class LowercaseClass(metaclass=LowercaseMeta):
   BAR = True
   def HELLO(self):
      print('hello')

print(dir(LowercaseClass))
LowercaseClass().hello()

Đầu ra

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar', 'hello']
hello

Ví dụ2 - Thêm một thuộc tính bổ sung vào lớp

class ListMeta(type):
   def __new__(mcs, name, bases, attrs):
      attrs['add'] = lambda self, value: self.append(value)
      return type.__new__(mcs, name, bases, attrs)
class MyList(list, metaclass=ListMeta):
pass
l = MyList()
l.add(1)
print(l)
def class_decorator(cls):
   cls.add = lambda self, value: self.append(value)
   return cls

@class_decorator
class MyList(list):
   pass
l = MyList()
l.append(1)
print(l)

Đầu ra

[1]
[1]

Thuộc tính __metaclass__

Trong python, chúng ta có một lớp hoặc một trong các cơ sở của nó có thuộc tính __metaclass__, nó được coi là loại siêu kính khác là siêu kính. Chúng ta có thể có thuộc tính __metaclass__ khi chúng ta viết một lớp dưới dạng -

Vì vậy, điều gì sẽ xảy ra khi chúng ta định nghĩa, một lớp như -

class hello(object):
   x = 10

Ở trên, lớp hello không có thuộc tính __metaclass__, vì vậy kiểu được sử dụng thay thế và việc tạo lớp được thực hiện dưới dạng -

hello = type(name, bases, dict)

Trong trường hợp xin chào của chúng tôi có một siêu kính được xác định -

class hello(object):
__metaclass__ = myMetaClass
pass

Bây giờ trong ví dụ trên, việc tạo lớp được thực hiện bằng cách sử dụng myMetaClass thay vì kiểu. Xin chào =myMetaClass (tên, căn cứ, dict)