নামকরণকৃতদের সাথে ডকাস্ট্রিং যুক্ত করছেন?


87

সহজেই কোনও নামডটপলে ডকুমেন্টেশন স্ট্রিং যুক্ত করা সম্ভব?

আমি চেষ্টা করেছিলাম

from collections import namedtuple

Point = namedtuple("Point", ["x", "y"])
"""
A point in 2D space
"""

# Yet another test

"""
A(nother) point in 2D space
"""
Point2 = namedtuple("Point2", ["x", "y"])

print Point.__doc__ # -> "Point(x, y)"
print Point2.__doc__ # -> "Point2(x, y)"

কিন্তু এটি এটি কাটা না। এটি কি অন্য কোনও উপায়ে করা সম্ভব?

উত্তর:


53

আপনি যেটি ফেরত দিয়েছিলেন তার আশেপাশে একটি সাধারণ, খালি র‌্যাপার ক্লাস তৈরি করে এটি অর্জন করতে পারেন namedtuple। আমি তৈরি করা একটি ফাইলের বিষয়বস্তু nt.py:

from collections import namedtuple

Point_ = namedtuple("Point", ["x", "y"])

class Point(Point_):
    """ A point in 2d space """
    pass

তারপরে পাইথন রিপাবলীতে:

>>> print nt.Point.__doc__
 A point in 2d space 

অথবা আপনি করতে পারেন:

>>> help(nt.Point)  # which outputs...
মডিউল এনটি-তে ক্লাস পয়েন্টে সহায়তা:

ক্লাস পয়েন্ট (পয়েন্ট)
 | 2 ডি স্পেসে একটি পয়েন্ট
 |  
 | পদ্ধতি সমাধানের আদেশ:
 | পয়েন্ট
 | পয়েন্ট
 | __ বিল্টিন __। টিপল
 | __ বিল্টিন __। অবজেক্ট
 ...

আপনি যদি প্রতিবার হাতে হাতে এটি করতে পছন্দ না করেন তবে এটি করার জন্য একটি কারখানার ক্রিয়াকলাপ লিখুন এটি তুচ্ছ:

def NamedTupleWithDocstring(docstring, *ntargs):
    nt = namedtuple(*ntargs)
    class NT(nt):
        __doc__ = docstring
    return NT

Point3D = NamedTupleWithDocstring("A point in 3d space", "Point3d", ["x", "y", "z"])

p3 = Point3D(1,2,3)

print p3.__doc__

কোন ফলাফল:

A point in 3d space

4
সাবক্লাসিং কি namedtupleপুরোদস্তুর "অবজেক্ট" তে রূপান্তর করবে না ? এর মাধ্যমে নাম-টিপলস থেকে কিছু পারফরম্যান্স লাভ হারাচ্ছেন?
exhuma

4
যদি আপনি __slots__ = ()উত্পন্ন সাবক্লাসে যুক্ত হন তবে আপনি ব্যবহারের স্মৃতি এবং পারফরম্যান্সের সুবিধাগুলি ধরে রাখতে পারবেনnamedtuple
ali_m

এটি এখনও এমআরওতে আরও একটি স্তর যুক্ত করে, যা কোনও ডাস্ট্রিংয়ের পক্ষে সমর্থনযোগ্য নয়। যাইহোক, একটি সহজেই বরাদ্দ করতে পারে __doc__এবং আসল অবজেক্টে একটি কাস্টমাইজড ডক্ট্রিং সংরক্ষণ করতে পারে।
বচসৌ

71

পাইথন 3-তে, কোনও মোড়কের প্রয়োজন হয় না, কারণ __doc__ধরণের বৈশিষ্ট্যগুলি লিখনযোগ্য।

from collections import namedtuple

Point = namedtuple('Point', 'x y')
Point.__doc__ = '''\
A 2-dimensional coordinate

x - the abscissa
y - the ordinate'''

এটি নিবিড়ভাবে একটি স্ট্যান্ডার্ড শ্রেণীর সংজ্ঞার সাথে মিলে যায়, যেখানে ডকস্ট্রিং শিরোনাম অনুসরণ করে।

class Point():
    '''A 2-dimensional coordinate

    x - the abscissa
    y - the ordinate'''
    <class code>

পাইথন 2 তে এটি কাজ করে না।

AttributeError: attribute '__doc__' of 'type' objects is not writable


64

একই জিনিসটি অবাক করে গুগলের মাধ্যমে এই পুরানো প্রশ্নটি জুড়ে এসেছিল।

কেবল এটি নির্দেশ করতে চেয়েছিলেন যে আপনি শ্রেণি ঘোষণার ডানদিকে নামটুপল () কল করে আরও পরিষ্কার করতে পারেন:

from collections import namedtuple

class Point(namedtuple('Point', 'x y')):
    """Here is the docstring."""

8
গুরুত্বপূর্ণ যে আপনি __slots__ = ()ক্লাস অন্তর্ভুক্ত । অন্যথায় আপনি __dict__আপনার অ্যাটর্সদের জন্য একটি তৈরি করেছেন , নামকরণের হালকা ওজনের স্বভাবটি হারাবেন।
বোল্টজমানব্রেন

34

সহজেই কোনও নামডটপলে ডকুমেন্টেশন স্ট্রিং যুক্ত করা সম্ভব?

হ্যাঁ, বিভিন্ন উপায়ে

সাবক্লাস টাইপিং.নামডটুপল - পাইথন ৩.+++

পাইথন ৩.6 হিসাবে আমরা সরাসরি একটি ডকস্ট্রিং (এবং টীকাগুলি) classদিয়ে একটি সংজ্ঞা ব্যবহার করতে পারি typing.NamedTuple:

from typing import NamedTuple

class Card(NamedTuple):
    """This is a card type."""
    suit: str
    rank: str

পাইথন 2 এর সাথে তুলনা করে, খালি ঘোষণা করা __slots__প্রয়োজন হয় না। পাইথন ৩.৮-তে, এটি সাবক্লাসগুলির জন্যও প্রয়োজনীয় নয়।

নোট করুন যে ঘোষণাটি __slots__অ-খালি হতে পারে না!

পাইথন 3-এ, আপনি সহজেই কোনও নেমটুপলে ডকটি পরিবর্তন করতে পারেন:

NT = collections.namedtuple('NT', 'foo bar')

NT.__doc__ = """:param str foo: foo name
:param list bar: List of bars to bar"""

আমরা যখন তাদের কাছে সাহায্যের জন্য কল করি তখন এটি তাদের জন্য লক্ষ্যটি দেখতে দেয়:

Help on class NT in module __main__:

class NT(builtins.tuple)
 |  :param str foo: foo name
 |  :param list bar: List of bars to bar
...

পাইথন 2 এ আমরা একই জিনিসটি অর্জন করতে যে সমস্যাগুলি করেছি তার তুলনায় এটি সত্যই সহজ।

পাইথন 2

পাইথন 2 এ আপনার দরকার

  • নামফলক সাবক্লাস, এবং
  • ঘোষণা __slots__ == ()

ঘোষনা __slots__করা একটি গুরুত্বপূর্ণ অংশ যা অন্য উত্তরগুলি এখানে মিস করে

আপনি যদি ঘোষণা না করেন __slots__- আপনি বাগগুলি প্রবর্তন করে দৃষ্টান্তগুলিতে পরিবর্তনীয় অ্যাড-হক বৈশিষ্ট্য যুক্ত করতে পারেন।

class Foo(namedtuple('Foo', 'bar')):
    """no __slots__ = ()!!!"""

এবং এখন:

>>> f = Foo('bar')
>>> f.bar
'bar'
>>> f.baz = 'what?'
>>> f.__dict__
{'baz': 'what?'}

অ্যাক্সেস করা হয়ে __dict__গেলে প্রতিটি উদাহরণ পৃথক তৈরি করবে __dict__(অভাব __slots__অন্যথায় কার্যকারিতা বাধাগ্রস্ত করবে না, তবে টিউপল, লঘুতা এবং ঘোষিত বৈশিষ্ট্যের হালকাতা সব নামকরণকারীর গুরুত্বপূর্ণ বৈশিষ্ট্য)।

আপনি __repr__যদি একটি কমান্ড লাইনে প্রতিধ্বনিত হয় যা আপনাকে একটি সমতুল্য বস্তু দিতে চান তাও আপনি চাইবেন:

NTBase = collections.namedtuple('NTBase', 'foo bar')

class NT(NTBase):
    """
    Individual foo bar, a namedtuple

    :param str foo: foo name
    :param list bar: List of bars to bar
    """
    __slots__ = ()

__repr__আপনি যদি আলাদা নামের সাথে বেসটি নেমটিপল বেস তৈরি করেন তবে এর মতো একটি প্রয়োজন (যেমন আমরা উপরে নামের স্ট্রিং যুক্তির সাহায্যে করেছি 'NTBase'):

    def __repr__(self):
        return 'NT(foo={0}, bar={1})'.format(
                repr(self.foo), repr(self.bar))

পুনরায় পরীক্ষা করতে, তাত্ক্ষণিকভাবে পরীক্ষা করে তারপরে পাসের সমতার জন্য পরীক্ষা করে eval(repr(instance))

nt = NT('foo', 'bar')
assert eval(repr(nt)) == nt

ডকুমেন্টেশন থেকে উদাহরণ

ডক্স এছাড়াও যেমন একটি উদাহরণ সংক্রান্ত দিতে, __slots__- আমি এটা আমার নিজের docstring যোগ করছি:

class Point(namedtuple('Point', 'x y')):
    """Docstring added here, not in original"""
    __slots__ = ()
    @property
    def hypot(self):
        return (self.x ** 2 + self.y ** 2) ** 0.5
    def __str__(self):
        return 'Point: x=%6.3f  y=%6.3f  hypot=%6.3f' % (self.x, self.y, self.hypot)

...

উপরের দেখানো সাবক্লাসটি __slots__একটি খালি টিপল সেট করে। এটি উদাহরণস্বরূপ অভিধানগুলি রোধ করে মেমরির প্রয়োজনীয়তাগুলি কম রাখতে সহায়তা করে।

এটি স্থান-ব্যবহারের ব্যবহারটি প্রমাণ করে (অন্য উত্তরটির মতো এখানে প্রস্তাবিত হয়), তবে নোট করুন যে আপনি যখন পদ্ধতিটি ক্রয়ের আদেশটি দেখেন, তখন আপনি ডিবাগ করেন, তাই আমি মূলত Baseপ্রত্যয় হিসাবে ব্যবহার করার পরামর্শ দিয়েছিলাম বেস বেসড জন্য:

>>> Point.mro()
[<class '__main__.Point'>, <class '__main__.Point'>, <type 'tuple'>, <type 'object'>]
                # ^^^^^---------------------^^^^^-- same names!        

__dict__যখন এটি ব্যবহার করে এমন একটি ক্লাস থেকে সাবক্লাসিং করার সময় সৃষ্টি রোধ করতে আপনাকে অবশ্যই এটি সাবক্লাসে ঘোষণা করতে হবে। আরও উত্তর দেওয়ার জন্য এই উত্তরটি__slots__ দেখুন ।


4
যদিও অন্যান্য উত্তরের মতো সংক্ষিপ্ত এবং স্পষ্ট নয়, এটি গ্রহণযোগ্য উত্তর হওয়া উচিত কারণ এটি এর গুরুত্বকে তুলে ধরে __slots__। এটি ছাড়াই, আপনি একটি নেমটুপলের হালকা ওজনের মান হারাচ্ছেন।
বোল্টজমানব্রেন

7

পাইথন ৩.৩ থেকে namedtupleঅবজেক্টের জন্য ডকস্ট্রিং আপডেট করা যায়।

থেকে whatsnew :

Point = namedtuple('Point', ['x', 'y'])
Point.__doc__ += ': Cartesian coodinate'
Point.x.__doc__ = 'abscissa'
Point.y.__doc__ = 'ordinate'


3

গৃহীত উত্তরের পরামর্শ অনুসারে একটি মোড়কের ক্লাস ব্যবহার করার দরকার নেই। কেবলমাত্র আক্ষরিক যোগ একটি docstring:

from collections import namedtuple

Point = namedtuple("Point", ["x", "y"])
Point.__doc__="A point in 2D space"

এর ফলাফলগুলি: (উদাহরণস্বরূপ ব্যবহার করে ipython3):

In [1]: Point?
Type:       type
String Form:<class '__main__.Point'>
Docstring:  A point in 2D space

In [2]: 

ভয়েল!


4
দ্রষ্টব্য: এটি কেবল পাইথন 3 এর জন্য বৈধ AttributeError: attribute '__doc__' of 'type' objects is not writable
টেলর এডমিস্টন

1

আপনি রেমন্ড হেট্টিংগার দ্বারা নামকৃত কারখানার ফাংশনটির নিজস্ব সংস্করণটি একত্রিত করতে এবং একটি an চ্ছিকdocstring যুক্তি যুক্ত করতে পারেন। তবে এটি সহজ হবে - এবং তাত্ক্ষণিকভাবে আরও ভাল - কেবল রেসিপি হিসাবে একই বেসিক কৌশল ব্যবহার করে আপনার নিজস্ব কারখানার ফাংশনটি সংজ্ঞায়িত করা। যে কোনও উপায়ে, আপনি পুনরায় ব্যবহারযোগ্য কিছু দিয়ে শেষ করবেন।

from collections import namedtuple

def my_namedtuple(typename, field_names, verbose=False,
                 rename=False, docstring=''):
    '''Returns a new subclass of namedtuple with the supplied
       docstring appended to the default one.

    >>> Point = my_namedtuple('Point', 'x, y', docstring='A point in 2D space')
    >>> print Point.__doc__
    Point(x, y):  A point in 2D space
    '''
    # create a base class and concatenate its docstring and the one passed
    _base = namedtuple(typename, field_names, verbose, rename)
    _docstring = ''.join([_base.__doc__, ':  ', docstring])

    # fill in template to create a no-op subclass with the combined docstring
    template = '''class subclass(_base):
        %(_docstring)r
        pass\n''' % locals()

    # execute code string in a temporary namespace
    namespace = dict(_base=_base, _docstring=_docstring)
    try:
        exec template in namespace
    except SyntaxError, e:
        raise SyntaxError(e.message + ':\n' + template)

    return namespace['subclass']  # subclass object created

0

আমি এই নামকরণ টিউপলটি দ্রুত তৈরি করতে এবং এর প্রতিটি পরামিতি সহ টিপলটি নথি করতে এই ফাংশনটি তৈরি করেছি:

from collections import namedtuple


def named_tuple(name, description='', **kwargs):
    """
    A named tuple with docstring documentation of each of its parameters
    :param str name: The named tuple's name
    :param str description: The named tuple's description
    :param kwargs: This named tuple's parameters' data with two different ways to describe said parameters. Format:
        <pre>{
            str: ( # The parameter's name
                str, # The parameter's type
                str # The parameter's description
            ),
            str: str, # The parameter's name: the parameter's description
            ... # Any other parameters
        }</pre>
    :return: collections.namedtuple
    """
    parameter_names = list(kwargs.keys())

    result = namedtuple(name, ' '.join(parameter_names))

    # If there are any parameters provided (such that this is not an empty named tuple)
    if len(parameter_names):
        # Add line spacing before describing this named tuple's parameters
        if description is not '':
            description += "\n"

        # Go through each parameter provided and add it to the named tuple's docstring description
        for parameter_name in parameter_names:
            parameter_data = kwargs[parameter_name]

            # Determine whether parameter type is included along with the description or
            # if only a description was provided
            parameter_type = ''
            if isinstance(parameter_data, str):
                parameter_description = parameter_data
            else:
                parameter_type, parameter_description = parameter_data

            description += "\n:param {type}{name}: {description}".format(
                type=parameter_type + ' ' if parameter_type else '',
                name=parameter_name,
                description=parameter_description
            )

            # Change the docstring specific to this parameter
            getattr(result, parameter_name).__doc__ = parameter_description

    # Set the docstring description for the resulting named tuple
    result.__doc__ = description

    return result

তারপরে আপনি একটি নতুন নামের টিপল তৈরি করতে পারেন:

MyTuple = named_tuple(
    "MyTuple",
    "My named tuple for x,y coordinates",
    x="The x value",
    y="The y value"
)

তারপরে বর্ণিত নামযুক্ত টিপলটিকে আপনার নিজস্ব ডেটা দিয়ে ইনস্ট্যান্ট করুন।

t = MyTuple(4, 8)
print(t) # prints: MyTuple(x=4, y=8)

help(MyTuple)পাইথন 3 কমান্ড লাইনের মাধ্যমে নির্বাহের সময় নিম্নলিখিতটি প্রদর্শিত হয়:

Help on class MyTuple:

class MyTuple(builtins.tuple)
 |  MyTuple(x, y)
 |
 |  My named tuple for x,y coordinates
 |
 |  :param x: The x value
 |  :param y: The y value
 |
 |  Method resolution order:
 |      MyTuple
 |      builtins.tuple
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  __getnewargs__(self)
 |      Return self as a plain tuple.  Used by copy and pickle.
 |
 |  __repr__(self)
 |      Return a nicely formatted representation string
 |
 |  _asdict(self)
 |      Return a new OrderedDict which maps field names to their values.
 |
 |  _replace(_self, **kwds)
 |      Return a new MyTuple object replacing specified fields with new values
 |
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |
 |  _make(iterable) from builtins.type
 |      Make a new MyTuple object from a sequence or iterable
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  __new__(_cls, x, y)
 |      Create new instance of MyTuple(x, y)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  x
 |      The x value
 |
 |  y
 |      The y value
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  _fields = ('x', 'y')
 |  
 |  _fields_defaults = {}
 |  
 |  ----------------------------------------------------------------------
 |  Methods inherited from builtins.tuple:
 |  
 |  __add__(self, value, /)
 |      Return self+value.
 |  
 |  __contains__(self, key, /)
 |      Return key in self.
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(self, key, /)
 |      Return self[key].
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __hash__(self, /)
 |      Return hash(self).
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __mul__(self, value, /)
 |      Return self*value.
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __rmul__(self, value, /)
 |      Return value*self.
 |  
 |  count(self, value, /)
 |      Return number of occurrences of value.
 |  
 |  index(self, value, start=0, stop=9223372036854775807, /)
 |      Return first index of value.
 |      
 |      Raises ValueError if the value is not present.

বিকল্পভাবে, আপনি এর মাধ্যমেও প্যারামিটারের ধরণ নির্দিষ্ট করতে পারেন:

MyTuple = named_tuple(
    "MyTuple",
    "My named tuple for x,y coordinates",
    x=("int", "The x value"),
    y=("int", "The y value")
)

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