পাইথনে "এট" (@) চিহ্নটি কী করবে?


578

আমি কিছু পাইথন কোড দেখছি যা @প্রতীকটি ব্যবহার করেছিল , তবে এটি কী করে তা আমার কোনও ধারণা নেই। পাইথন ডক্স অনুসন্ধান করার জন্য কী কী সন্ধান করতে হবে তাও আমি জানি না বা @প্রতীকটি অন্তর্ভুক্ত করা হলে গুগল প্রাসঙ্গিক ফলাফল দেয় না ।

উত্তর:


303

@একটি রেখার শুরুতে একটি চিহ্ন শ্রেণি, ফাংশন এবং পদ্ধতি সজ্জকারদের জন্য ব্যবহৃত হয় ।

এখানে আরও পড়ুন:

পিইপি 318: সজ্জা

পাইথন সজ্জা

পাইথন সজ্জাকারীদের মধ্যে সর্বাধিক সাধারণ সজ্জিত হলেন:

@property

@classmethod

@staticmethod

আপনি যদি @কোনও লাইনের মাঝখানে কোনও দেখতে পান তবে ম্যাট্রিক্সের গুণটি এটি আলাদা। যে ঠিকানাগুলি ব্যবহার করে সেগুলির অন্যান্য উত্তরগুলি দেখতে নীচে স্ক্রোল করুন @


31
দেখে মনে হচ্ছে এটি ম্যাট্রিক্সের গুণক অপারেটরও হতে পারে: stackoverflow.com/a/21563036/5049813
প্রো কিউ

@ ডেকোরেটরগুলিও যুক্ত করা যায়
বিজয়

346

উদাহরণ

class Pizza(object):
    def __init__(self):
        self.toppings = []

    def __call__(self, topping):
        # When using '@instance_of_pizza' before a function definition
        # the function gets passed onto 'topping'.
        self.toppings.append(topping())

    def __repr__(self):
        return str(self.toppings)

pizza = Pizza()

@pizza
def cheese():
    return 'cheese'
@pizza
def sauce():
    return 'sauce'

print pizza
# ['cheese', 'sauce']

এ থেকে জানা যায় function/ method/ classতোমার পরে একটি সংজ্ঞায়িত করছি প্রসাধক মাত্র মূলত একটি হিসাবে পাস করা হয়েছে argumentথেকে function/ methodঅবিলম্বে পরে @সাইন ইন করুন।

প্রথম দেখা

Microframework বোতল প্রবর্তন টেকনিক থেকে নিম্নলিখিত বিন্যাসে খুব শুরু:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

এটি পরিবর্তে অনুবাদ করে:

rule      = "/"
view_func = hello
# They go as arguments here in 'flask/app.py'
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
    pass

এটি বুঝতে পেরে অবশেষে আমি ফ্লাস্কের সাথে শান্তিতে অনুভব করতে পারলাম।


7
ফ্লাস্কস এর ক্ষেত্রে app.route("/"): এই ফাংশনটি একটি ফাংশন প্রদান করে, যা আপনি আপনার hello()যুক্তি হিসাবে উপস্থাপন করেন
shaqed

3
এখানে সাজসজ্জার থাকার সিনথেটিক বা ব্যবহারিক সুবিধা কী, এর পরিবর্তে (উদাহরণস্বরূপ) কেবল app.route("/", hello)সংজ্ঞা দেওয়ার সাথে সাথে কিছু কল করা helloবা helloযুক্তিগুলিতে ল্যাম্বডা হিসাবে সংজ্ঞায়িত করার পরিবর্তে app.route? (আধুনিক উদাহরণ Node.js সঙ্গে সাধারণ http.Serverএবং এক্সপ্রেস রুট।)
iono

185

এই কোড স্নিপেট:

def decorator(func):
   return func

@decorator
def some_func():
    pass

এই কোডের সমতুল্য:

def decorator(func):
    return func

def some_func():
    pass

some_func = decorator(some_func)

সাজসজ্জার সংজ্ঞা হিসাবে আপনি কিছু সংশোধিত জিনিস যুক্ত করতে পারেন যা কোনও ফাংশন দ্বারা সাধারণত ফিরে আসবে না।


1
এই লাইনে s "ome_func = অলঙ্করণকারী (কিছু_ফঙ্ক)", প্রথম কিছু_ফঙ্ক একটি পরিবর্তনশীল = ফাংশনটির কিছু_ফঙ্ক, সঠিক?
ভাইরাগস

147

পাইথন 3.5 তে আপনি @অপারেটর হিসাবে ওভারলোড করতে পারেন । এটি এর নামকরণ করা হয়েছে __matmul__, কারণ এটি ম্যাট্রিক্সের গুণকে করার জন্য ডিজাইন করা হয়েছে তবে এটি আপনি যা চান তা হতে পারে। বিস্তারিত জানার জন্য PEP465 দেখুন ।

এটি ম্যাট্রিক্সের গুণনের একটি সরল বাস্তবায়ন।

class Mat(list):
    def __matmul__(self, B):
        A = self
        return Mat([[sum(A[i][k]*B[k][j] for k in range(len(B)))
                    for j in range(len(B[0])) ] for i in range(len(A))])

A = Mat([[1,3],[7,5]])
B = Mat([[6,8],[4,2]])

print(A @ B)

এই কোডটি দেয়:

[[18, 14], [62, 66]]

14
আপনার কাছে @=(ইন-প্লেস) অপারেটরও রয়েছে __imatmul__
পল জিডি

এর মতো আর কোনও ওভারিডেবল অপারেটর কি আছে? আমি জানি __add__এবং __sub__যথাক্রমে + এবং - এর সাথে সংযুক্ত হয়েছি , তবে @সাইন এর আগে কখনও শুনিনি । সেখানে অন্য কেউ লুকিয়ে আছে?
থমাস কিম্বার

103

পাইথনে "এট" (@) চিহ্নটি কী করবে?

সংক্ষেপে, এটি ডেকোরেটর সিনট্যাক্স এবং ম্যাট্রিক্স গুণনের জন্য ব্যবহৃত হয়।

সাজসজ্জার প্রসঙ্গে, এই সিনট্যাক্স:

@decorator
def decorated_function():
    """this function is decorated"""

এর সমতুল্য:

def decorated_function():
    """this function is decorated"""

decorated_function = decorator(decorated_function)

ম্যাট্রিক্স গুণ প্রসঙ্গে, a @ bপূজা a.__matmul__(b)- এই সিনট্যাক্স উপার্জন:

a @ b

সমতুল্য

dot(a, b)

এবং

a @= b

সমতুল্য

a = dot(a, b)

যেখানে dot, উদাহরণস্বরূপ, numpy ম্যাট্রিক্স গুণ ফাংশন এবং হয় aএবং bম্যাট্রিক্স আছে।

আপনি কীভাবে এটি নিজে আবিষ্কার করতে পারেন?

পাইথন ডক্স অনুসন্ধান করার জন্য কী সন্ধান করতে হবে তাও আমি জানি না বা @ প্রতীকটি অন্তর্ভুক্ত করা হলে গুগল প্রাসঙ্গিক ফলাফল দেয় না।

পাইথন সিনট্যাক্সের একটি বিশেষ অংশটি কী করে তার পরিবর্তে যদি আপনি সম্পূর্ণরূপে দেখতে চান তবে সরাসরি ব্যাকরণ ফাইলটি দেখুন। পাইথন 3 শাখার জন্য:

~$ grep -C 1 "@" cpython/Grammar/Grammar 

decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+
--
testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=')
--
arith_expr: term (('+'|'-') term)*
term: factor (('*'|'@'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power

আমরা এখানে @তিনটি প্রসঙ্গে ব্যবহার করা দেখতে পারি :

  • আলোকচিত্রী
  • কারণগুলির মধ্যে অপারেটর
  • একটি বর্ধিত অ্যাসাইনমেন্ট অপারেটর

সাজসজ্জার সিনট্যাক্স:

"ডেকোরেটর পাইথন ডক্স" এর জন্য একটি গুগল অনুসন্ধান শীর্ষ ফলাফলগুলির মধ্যে একটি হিসাবে দেয়, "পাইথন ল্যাঙ্গুয়েজ রেফারেন্স" এর "যৌগিক বিবৃতি" বিভাগ। ফাংশন সংজ্ঞায়নের অংশে স্ক্রোল করে যা আমরা "সজ্জা" শব্দটি অনুসন্ধান করে খুঁজে পেতে পারি, আমরা দেখতে পাই যে এখানে অনেক কিছু পড়ার দরকার আছে। তবে "সাজসজ্জা" শব্দটি শব্দকোষের একটি লিঙ্ক , যা আমাদের বলে:

প্রসাধক

একটি ফাংশন অন্য ফাংশনকে ফিরিয়ে দেয়, সাধারণত @wrapperসিনট্যাক্স ব্যবহার করে একটি ফাংশন রূপান্তর হিসাবে প্রয়োগ করা হয় । সাজসজ্জার জন্য সাধারণ উদাহরণ classmethod()এবং staticmethod()

সাজসজ্জার সিনট্যাক্স নিছক সিনট্যাকটিক চিনি, নিম্নলিখিত দুটি কার্য সংজ্ঞা শব্দার্থগতভাবে সমতুল্য:

def f(...):
    ...
f = staticmethod(f)

@staticmethod
def f(...):
    ...

ক্লাসগুলির জন্য একই ধারণাটি বিদ্যমান, তবে সেখানে কম ব্যবহৃত হয়। সজ্জকার সম্পর্কে আরও তথ্যের জন্য ফাংশন সংজ্ঞা এবং শ্রেণি সংজ্ঞাগুলির জন্য ডকুমেন্টেশন দেখুন।

সুতরাং, আমরা এটি দেখতে

@foo
def bar():
    pass

শব্দার্থগতভাবে একই:

def bar():
    pass

bar = foo(bar)

এগুলি ঠিক একই নয় কারণ পাইথন ডিকোরিটার ( @) সিনট্যাক্সের সাথে বারের আগে foo এক্সপ্রেশন (যা ডটেড লুক এবং একটি ফাংশন কল হতে পারে ) মূল্যায়ন করে, তবে অন্য ক্ষেত্রে বারের পরে ফু এক্সপ্রেশনকে মূল্যায়ন করে ।

(যদি এই কোডটি আপনার কোডের অর্থের মধ্যে পার্থক্য করে তবে আপনার জীবন নিয়ে আপনি কী করছেন তা আপনার পুনর্বিবেচনা করা উচিত, কারণ এটি রোগতাত্ত্বিক হবে))

সজ্জিত সাজসজ্জা

আমরা যদি ফাংশন সংজ্ঞা সিনট্যাক্স ডকুমেন্টেশনে ফিরে যাই তবে আমরা দেখতে পাই:

@f1(arg)
@f2
def func(): pass

মোটামুটি সমান

def func(): pass
func = f1(arg)(f2(func))

এটি এমন একটি বিক্ষোভ যা আমরা কোনও ফাংশনটিকে কল করতে পারি যা প্রথমে ডেকরেটার, পাশাপাশি স্ট্যাক ডেকোরেটর। পাইথনে ফাংশনগুলি প্রথম শ্রেণীর অবজেক্টস - যার অর্থ আপনি কোনও ফাংশনটিকে অন্য কোনও ফাংশনের পক্ষে যুক্তি হিসাবে পাস করতে পারেন এবং ফাংশনগুলি ফিরিয়ে দিতে পারেন। সাজসজ্জাকারীরা এই দুটি জিনিসই করেন।

যদি আমরা অলঙ্করণকারীদের স্ট্যাক করি, তবে সংজ্ঞায়িত হিসাবে ফাংশনটি প্রথমে তার উপরে প্রথমে সাজসজ্জার কাছে পৌঁছে যায়, তারপরে পরবর্তী এবং আরও কিছু।

এটি সজ্জকারদের @প্রসঙ্গে ব্যবহারের পরিমাণের পরিমাণ ।

চালক, @

ভাষা রেফারেন্সের লেজিকাল এনালাইসিস বিভাগে, আমাদের অপারেটরগুলির উপর একটি বিভাগ রয়েছে @, যার মধ্যে এটি অন্তর্ভুক্ত রয়েছে , যা এটিকে একটি অপারেটরও করে তোলে:

নিম্নলিখিত টোকেনগুলি অপারেটরগুলি:

+       -       *       **      /       //      %      @
<<      >>      &       |       ^       ~
<       >       <=      >=      ==      !=

এবং পরবর্তী পৃষ্ঠায়, ডেটা মডেল, আমরা অনুকরণীয় সংখ্যার প্রকার বিভাগ ,

object.__add__(self, other)
object.__sub__(self, other) 
object.__mul__(self, other) 
object.__matmul__(self, other) 
object.__truediv__(self, other) 
object.__floordiv__(self, other)

[...] এই পদ্ধতির বাইনারি গাণিতিক অপারেশন (বাস্তবায়ন বলা হয় +, -, *,@ , /, //, [...]

এবং আমরা এর __matmul__সাথে মিল রেখে দেখি @। যদি আমরা "ম্যাটমুল" এর জন্য ডকুমেন্টেশনগুলি সন্ধান করি আমরা এর লিঙ্ক পাই পাইথন 3.5 তে নতুন কী আছে তার পাই "পিইপি 465 - ম্যাট্রিক্স গুণণের জন্য একটি উত্সর্গীকৃত ইনফিক্স অপারেটর" শিরোনামের অধীনে "ম্যাটমুল" দিয়ে new

এটি নির্ধারণ করে প্রয়োগ করা যেতে পারে __matmul__(),__rmatmul__() এবং __imatmul__()জন্য, নিয়মিত প্রতিফলিত হয় এবং ইন-জায়গা ম্যাট্রিক্স গুণ।

(সুতরাং এখন আমরা এটি শিখি @= এটি স্থানের সংস্করণ)। এটি আরও ব্যাখ্যা করে:

গণিত, বিজ্ঞান, প্রকৌশল এবং বিভাগের অনেক ক্ষেত্রে ম্যাট্রিক্সের গুণটি একটি বিশেষ প্রচলিত ক্রিয়াকলাপ এবং @ যোগ করা ক্লিনার কোড লেখার অনুমতি দেয়:

S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)

পরিবর্তে:

S = dot((dot(H, beta) - r).T,
        dot(inv(dot(dot(H, V), H.T)), dot(H, beta) - r))

যদিও এই অপারেটরটি প্রায় কোনও কিছু করতে ওভারলোড করা যায় numpy, উদাহরণস্বরূপ, অ্যারে এবং ম্যাট্রিকেসের অভ্যন্তরীণ এবং বাহ্যিক পণ্য গণনা করার জন্য আমরা এই বাক্য গঠনটি ব্যবহার করব:

>>> from numpy import array, matrix
>>> array([[1,2,3]]).T @ array([[1,2,3]])
array([[1, 2, 3],
       [2, 4, 6],
       [3, 6, 9]])
>>> array([[1,2,3]]) @ array([[1,2,3]]).T
array([[14]])
>>> matrix([1,2,3]).T @ matrix([1,2,3])
matrix([[1, 2, 3],
        [2, 4, 6],
        [3, 6, 9]])
>>> matrix([1,2,3]) @ matrix([1,2,3]).T
matrix([[14]])

ইনপ্লেস ম্যাট্রিক্স গুণ: @=

পূর্ববর্তী ব্যবহার নিয়ে গবেষণা করার সময় আমরা শিখেছি যে ইনপ্লেস ম্যাট্রিক্সের গুণও রয়েছে। যদি আমরা এটি ব্যবহারের চেষ্টা করি তবে আমরা দেখতে পাই এটি এখনও অলস জন্য প্রয়োগ করা হয়নি:

>>> m = matrix([1,2,3])
>>> m @= m.T
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: In-place matrix multiplication is not (yet) supported. Use 'a = a @ b' instead of 'a @= b'.

যখন এটি বাস্তবায়ন করা হয়, তখন আমি ফলাফলটি দেখতে এমনটি আশা করি:

>>> m = matrix([1,2,3])
>>> m @= m.T
>>> m
matrix([[14]])

36

পাইথনে "এট" (@) চিহ্নটি কী করবে?

@ চিহ্ন একটি অন্বিত চিনি পাইথন ব্যবহার করতে প্রদান করে decorator,
প্রশ্ন ভাষান্তর করার জন্য, এটা হচ্ছে ঠিক সম্পর্কে প্রসাধক পাইথন মধ্যে কি করে?

এটিকে সরল রাখুন decoratorআপনি প্রদত্ত ফাংশনটির সংজ্ঞাটি এর অভ্যন্তরীণ স্পর্শ ছাড়াই (এটি বন্ধ) সংশোধন করার অনুমতি দিন।
আপনি যখন তৃতীয় পক্ষ থেকে দুর্দান্ত প্যাকেজ আমদানি করেন এটি সর্বাধিক ক্ষেত্রে। আপনি এটিকে ভিজ্যুয়ালাইজ করতে পারেন, আপনি এটি ব্যবহার করতে পারেন তবে আপনি এর অভ্যন্তরীণতম এবং এর হৃদয়কে স্পর্শ করতে পারবেন না।

এখানে একটি দ্রুত উদাহরণ দেওয়া আছে,
ধরুন আমি read_a_bookআইপিথনের কোনও ফাংশন সংজ্ঞায়িত করেছি

In [9]: def read_a_book():
   ...:     return "I am reading the book: "
   ...: 
In [10]: read_a_book()
Out[10]: 'I am reading the book: '

আপনি দেখুন, আমি এটিতে একটি নাম যুক্ত করতে ভুলে গেছি।
কীভাবে এ জাতীয় সমস্যা সমাধান করবেন? অবশ্যই, আমি ফাংশনটি আবার সংজ্ঞায়িত করতে পারলাম:

def read_a_book():
    return "I am reading the book: 'Python Cookbook'"

তবুও, যদি আমাকে মূল ফাংশনটি পরিচালনা করতে না দেওয়া হয়, বা যদি এমন হাজার হাজার ফাংশন পরিচালনা করতে হয়।

সমস্যাটি আলাদা চিন্তা করে সমাধান করুন এবং একটি নতুন_ফাংশনটি সংজ্ঞায়িত করুন

def add_a_book(func):
    def wrapper():
        return func() + "Python Cookbook"
    return wrapper

তারপর এটি নিয়োগ।

In [14]: read_a_book = add_a_book(read_a_book)
In [15]: read_a_book()
Out[15]: 'I am reading the book: Python Cookbook'

তদা, আপনি দেখুন, আমি read_a_bookএটি অভ্যন্তরীণ বন্ধটি স্পর্শ না করে সংশোধন করেছি । কিছুই আমাকে সজ্জিত করে না decorator

কি সম্পর্কে @

@add_a_book
def read_a_book():
    return "I am reading the book: "
In [17]: read_a_book()
Out[17]: 'I am reading the book: Python Cookbook'

@add_a_bookবলার মতো অভিনব এবং সহজ উপায় read_a_book = add_a_book(read_a_book), এটি একটি সিনট্যাকটিক চিনি, এটি সম্পর্কে আরও কল্পিত কিছু নেই।


16

আপনি যদি একটি পাইথন নোটবুক যা ব্যবহার করছে কিছু কোড উল্লেখ করা হয় তাহলে Numpy গ্রন্থাগার, তারপর @ operatorঅর্থ ম্যাট্রিক্স গুণ । উদাহরণ স্বরূপ:

import numpy as np
def forward(xi, W1, b1, W2, b2):
    z1 = W1 @ xi + b1
    a1 = sigma(z1)
    z2 = W2 @ a1 + b2
    return z2, a1


6

ফাংশন এবং পদ্ধতি মোড়ানো ( অজানা একটি ফাংশন যা একটি ক্রিয়াকলাপ গ্রহণ করে এবং উন্নতকে ফিরিয়ে দেয়) সহজেই পড়তে ও বুঝতে সহজেই পাইথনে সাজসজ্জারকে যুক্ত করা হয়েছিল । আসল ব্যবহারের ক্ষেত্রটি ছিল তাদের সংজ্ঞাটির শিরোনামে শ্রেণি পদ্ধতি বা স্থির পদ্ধতি হিসাবে পদ্ধতিগুলি সংজ্ঞায়িত করতে সক্ষম। সাজসজ্জার সিনট্যাক্স ব্যতীত এর জন্য বরং একটি বিচ্ছিন্ন এবং পুনরাবৃত্তি সংজ্ঞা প্রয়োজন:

class WithoutDecorators:
def some_static_method():
    print("this is static method")
some_static_method = staticmethod(some_static_method)

def some_class_method(cls):
    print("this is class method")
some_class_method = classmethod(some_class_method)

যদি সাজসজ্জার সিনট্যাক্স একই উদ্দেশ্যে ব্যবহার করা হয়, কোডটি খাটো এবং বুঝতে সহজ:

class WithDecorators:
    @staticmethod
    def some_static_method():
        print("this is static method")

    @classmethod
    def some_class_method(cls):
        print("this is class method")

সাধারণ বাক্য গঠন এবং সম্ভাব্য বাস্তবায়ন

সাজসজ্জা সাধারণত একটি নামকৃত বস্তু ( ল্যাম্বডা এক্সপ্রেশন অনুমোদিত নয় ) যা ডাকা হলে এটি একটি একক যুক্তি গ্রহণ করে (এটি সজ্জিত ফাংশন হবে) এবং অন্য কলযোগ্য বস্তুটি ফেরত দেয়। প্রাক কল্পনা সহ "ফাংশন" এর পরিবর্তে এখানে "কলযোগ্য" ব্যবহৃত হয়। যদিও সাজসজ্জারগুলি প্রায়শই পদ্ধতি এবং কার্যাবলির সুযোগে আলোচিত হয়, তবে সেগুলি তাদের মধ্যে সীমাবদ্ধ নয়। প্রকৃতপক্ষে, কলযোগ্য যেকোনও জিনিস (যে কোনও বস্তু যা _call__ পদ্ধতি প্রয়োগ করে তাকে কলযোগ্য হিসাবে বিবেচনা করা হয়), এটি ডেকরেটর হিসাবে ব্যবহার করা যেতে পারে এবং প্রায়শই তাদের দ্বারা প্রত্যাবর্তিত বস্তুগুলি সাধারণ ফাংশন নয় বরং আরও call_ পদ্ধতি প্রয়োগ করে আরও জটিল শ্রেণীর আরও উদাহরণ।

সাজসজ্জার সিনট্যাক্স কেবল একটি সিনট্যাকটিক চিনি । নিম্নলিখিত সাজসজ্জার ব্যবহার বিবেচনা করুন:

@some_decorator
def decorated_function():
    pass

এটি সর্বদা সুস্পষ্ট সাজসজ্জার কল এবং ফাংশন পুনরায় নিয়োগের মাধ্যমে প্রতিস্থাপন করা যেতে পারে:

def decorated_function():
    pass
decorated_function = some_decorator(decorated_function)

তবে, আধুনিকগুলি কম পঠনযোগ্য এবং একক ফাংশনে একাধিক সজ্জকার ব্যবহার করা হয়েছে কিনা তা বোঝা খুব শক্ত। সজ্জিতগুলি নীচে প্রদর্শিত হিসাবে একাধিক বিভিন্ন উপায়ে ব্যবহার করা যেতে পারে:

একটি ফাংশন হিসাবে

কাস্টম অলঙ্করণকারীদের লেখার অনেকগুলি উপায় রয়েছে তবে সহজ উপায় হ'ল মূল ফাংশন কলটি মোড়ানো এমন একটি ফাংশন লিখে ফাংশন লিখুন।

জেনেরিক নিদর্শনগুলি নিম্নরূপ:

def mydecorator(function):
    def wrapped(*args, **kwargs):
        # do some stuff before the original
        # function gets called
        result = function(*args, **kwargs)
        # do some stuff after function call and
        # return the result
        return result
    # return wrapper as a decorated function
    return wrapped

ক্লাস হিসাবে

প্রায়শই সর্বদা সজ্জা ফাংশন ব্যবহার করে প্রয়োগ করা যেতে পারে, কিছু পরিস্থিতিতে রয়েছে যখন ব্যবহারকারী-সংজ্ঞায়িত ক্লাসগুলি ব্যবহার করা একটি ভাল বিকল্প। এটি প্রায়শই সত্য হয় যখন সাজসজ্জার জটিল প্যারামিট্রাইজেশন প্রয়োজন হয় বা এটি একটি নির্দিষ্ট অবস্থার উপর নির্ভর করে।

শ্রেণি হিসাবে একটি ননপ্রেমেট্রাইজড ডিকোয়টারের জেনেরিক প্যাটার্নটি নিম্নরূপ:

class DecoratorAsClass:
    def __init__(self, function):
        self.function = function

    def __call__(self, *args, **kwargs):
        # do some stuff before the original
        # function gets called
        result = self.function(*args, **kwargs)
        # do some stuff after function call and
        # return the result
        return result

প্যারমেট্রাইজিং সজ্জা

আসল কোডে, প্রায়শই প্যারামেট্রাইজড হতে পারে এমন সজ্জা ব্যবহার করার প্রয়োজন হয়। যখন ফাংশনটি ডেকরেটার হিসাবে ব্যবহৃত হয়, তখন সমাধানটি সহজ। দ্বিতীয় স্তরের মোড়ক ব্যবহার করতে হয়। এখানে সাজসজ্জার একটি সাধারণ উদাহরণ যা সজ্জিত ক্রিয়াকলাপের যতবার বলা হয় তার নির্দিষ্ট সংখ্যার বারবার পুনরাবৃত্তি করে:

def repeat(number=3):
"""Cause decorated function to be repeated a number of times.

Last value of original function call is returned as a result
:param number: number of repetitions, 3 if not specified
"""
def actual_decorator(function):
    def wrapper(*args, **kwargs):
        result = None
        for _ in range(number):
            result = function(*args, **kwargs)
        return result
    return wrapper
return actual_decorator

এইভাবে সংজ্ঞায়িত সাজসজ্জা প্যারামিটারগুলি গ্রহণ করতে পারে:

>>> @repeat(2)
... def foo():
...     print("foo")
...
>>> foo()
foo
foo

মনে রাখবেন যে প্যারামিট্রাইজড ডেকোরিটারের যদি তার আর্গুমেন্টগুলির জন্য ডিফল্ট মান থাকে তবে এর নামের পরে প্রথম বন্ধনী প্রয়োজন। পূর্বনির্ধারিত সাজসজ্জারটি ডিফল্ট আর্গুমেন্টগুলির সাথে সঠিকভাবে ব্যবহার করার উপায়:

>>> @repeat()
... def bar():
...     print("bar")
...
>>> bar()
bar
bar
bar

শেষ পর্যন্ত সম্পত্তি সহ সজ্জা দেখতে দিন।

প্রোপার্টি

বৈশিষ্ট্যগুলি একটি অন্তর্নির্মিত বর্ণনাকারী প্রকার সরবরাহ করে যা পদ্ধতিগুলির একটি সেটের সাথে কোনও বৈশিষ্ট্যকে কীভাবে সংযুক্ত করতে হয় তা জানে। একটি সম্পত্তি চারটি alচ্ছিক আর্গুমেন্ট নেয়: fget, fset, fdel, এবং ডক। শেষেরটি একটি ডকাস্ট্রিং সংজ্ঞায়িত করার জন্য সরবরাহ করা যেতে পারে যা গুণাবলীর সাথে যুক্ত এটি যেন কোনও পদ্ধতি। এখানে একটি আয়তক্ষেত্র শ্রেণীর উদাহরণ যা দুটি কোণার পয়েন্ট সংরক্ষণ করে এমন বৈশিষ্ট্যগুলির সরাসরি অ্যাক্সেস বা প্রস্থ এবং উচ্চতার বৈশিষ্ট্যগুলি ব্যবহার করে নিয়ন্ত্রণ করা যেতে পারে:

class Rectangle:
    def __init__(self, x1, y1, x2, y2):
        self.x1, self.y1 = x1, y1
        self.x2, self.y2 = x2, y2

    def _width_get(self):
        return self.x2 - self.x1

    def _width_set(self, value):
        self.x2 = self.x1 + value

    def _height_get(self):
        return self.y2 - self.y1

    def _height_set(self, value):
        self.y2 = self.y1 + value

    width = property(
        _width_get, _width_set,
        doc="rectangle width measured from left"
    )
    height = property(
        _height_get, _height_set,
        doc="rectangle height measured from top"
    )

    def __repr__(self):
        return "{}({}, {}, {}, {})".format(
            self.__class__.__name__,
            self.x1, self.y1, self.x2, self.y2
    )

বৈশিষ্ট্য তৈরির জন্য সর্বোত্তম বাক্য গঠনটি হ'ল সম্পত্তিটিকে ডেকরেটর হিসাবে ব্যবহার করা। এটি শ্রেণীর অভ্যন্তরে পদ্ধতির স্বাক্ষরের সংখ্যা হ্রাস করবে এবং কোডকে আরও পাঠযোগ্য ও রক্ষণাবেক্ষণযোগ্য করে তুলবে । উপরের শ্রেণীর সাজসজ্জার দ্বারা:

class Rectangle:
    def __init__(self, x1, y1, x2, y2):
        self.x1, self.y1 = x1, y1
        self.x2, self.y2 = x2, y2

    @property
    def width(self):
        """rectangle height measured from top"""
        return self.x2 - self.x1

    @width.setter
    def width(self, value):
        self.x2 = self.x1 + value

    @property
    def height(self):
        """rectangle height measured from top"""
        return self.y2 - self.y1

    @height.setter
    def height(self, value):
        self.y2 = self.y1 + value

2

অন্যের কাছে অন্যরকম কী আছে তা বলতে: হ্যাঁ, এটি একটি সজ্জাকারী।

পাইথনে, এটি এর মতো:

  1. একটি ফাংশন তৈরি করা (@ কলের নীচে অনুসরণ করা)
  2. আপনার তৈরি ফাংশনটি পরিচালনা করতে অন্য ক্রিয়াকলাপের ডাক। এটি একটি নতুন ফাংশন দেয়। আপনি যে ফাংশনটি কল করছেন তা হ'ল @ এর যুক্তি।
  3. নতুন ফাংশন দিয়ে সংজ্ঞায়িত ফাংশনটি প্রতিস্থাপন করে ফিরে আসুন।

এটি সমস্ত ধরণের দরকারী জিনিসের জন্য ব্যবহার করা যেতে পারে, এটি সম্ভব হয়েছে কারণ ফাংশনগুলি হ'ল বস্তু এবং কেবল প্রয়োজনীয় কেবলমাত্র নির্দেশাবলী।


2

@ প্রতীক প্লাইটাটা / প্যান্ডাস ডেটা ফ্রেম ক্যোয়ারির ভিতরে ভেরিয়েবলগুলি অ্যাক্সেস করতে ব্যবহৃত হয় pandas.DataFrame.query। উদাহরণ:

df = pandas.DataFrame({'foo': [1,2,15,17]})
y = 10
df >> query('foo > @y') # plydata
df.query('foo > @y') # pandas

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.