পাইথনে মিউটেবল টুপল নামের অস্তিত্ব?


120

যে কেউ নামটুপলে সংশোধন করতে পারে বা বিকল্প শ্রেণি সরবরাহ করতে পারে যাতে এটি পরিবর্তনযোগ্য বস্তুর জন্য কাজ করে?

মূলত পাঠযোগ্যতার জন্য, আমি নেমটুপলের সাথে অনুরূপ কিছু চাই যা এটি করে:

from Camelot import namedgroup

Point = namedgroup('Point', ['x', 'y'])
p = Point(0, 0)
p.x = 10

>>> p
Point(x=10, y=0)

>>> p.x *= 10
Point(x=100, y=0)

ফলস্বরূপ অবজেক্টটি আচার করা অবশ্যই সম্ভব। এবং নামের টিউপলের বৈশিষ্ট্য অনুসারে, উপস্থাপিত হওয়ার সময় আউটপুট ক্রমের সাথে বস্তুটি নির্মাণের সময় অবশ্যই প্যারামিটার তালিকার ক্রমের সাথে মিল রাখতে হবে।


3
এছাড়াও দেখুন: stackoverflow.com/q/5131044 । আপনি কেবল একটি অভিধান ব্যবহার করতে পারবেন না এমন কোনও কারণ আছে?
সেনশিন

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

সঙ্গে ভিন্ন namedtupleগুলি, মনে হচ্ছে কোন প্রয়োজন সূচক দ্বারা বৈশিষ্ট্যাবলী রেফারেন্স, অর্থাত্ তাই পাবে আছে p[0]এবং p[1]রেফারেন্স কিছু করতে বিকল্প উপায়ে হবে xএবং yযথাক্রমে সঠিক?
মার্টিনো

আদর্শভাবে, হ্যাঁ, নাম ছাড়াও প্লেইন টুপলের মতো পজিশনে সূচকযোগ্য এবং টিপলের মতো আনপ্যাকগুলি। এই অ্যাক্টিস্টেট রেসিপিটি নিকটে, তবে আমি বিশ্বাস করি এটি একটি অর্ডারডিক্টের পরিবর্তে একটি নিয়মিত অভিধান ব্যবহার করে। কোড.activestate.com/recines/500261
আলেকজান্ডার

2
একটি পরিবর্তনীয় নামটুপলকে একটি শ্রেণি বলা হয়।
gbtimmon

উত্তর:


131

সেখানে একটি চপল বিকল্প নেই collections.namedtuple- recordclass

এটির মতো একই এপিআই এবং মেমরির পদচিহ্ন রয়েছে namedtupleএবং এটি অ্যাসাইনমেন্টগুলি সমর্থন করে (এটি আরও দ্রুত হওয়া উচিত)। উদাহরণ স্বরূপ:

from recordclass import recordclass

Point = recordclass('Point', 'x y')

>>> p = Point(1, 2)
>>> p
Point(x=1, y=2)
>>> print(p.x, p.y)
1 2
>>> p.x += 2; p.y += 3; print(p)
Point(x=3, y=5)

অজগর জন্য 3.6 এবং উচ্চতর recordclass(0.5 থেকে) সমর্থন টাইপ ইঙ্গিতগুলি:

from recordclass import recordclass, RecordClass

class Point(RecordClass):
   x: int
   y: int

>>> Point.__annotations__
{'x':int, 'y':int}
>>> p = Point(1, 2)
>>> p
Point(x=1, y=2)
>>> print(p.x, p.y)
1 2
>>> p.x += 2; p.y += 3; print(p)
Point(x=3, y=5)

আরও একটি সম্পূর্ণ উদাহরণ রয়েছে (এটিতে পারফরম্যান্সের তুলনাও অন্তর্ভুক্ত)।

যেহেতু 0.9 recordclassগ্রন্থাগারটি অন্য বৈকল্পিক সরবরাহ করে - recordclass.structclassকারখানার ফাংশন। এটি ক্লাস তৈরি করতে পারে, যার উদাহরণগুলি __slots__বেসড দৃষ্টান্তগুলির চেয়ে কম মেমরি দখল করে । এটি বৈশিষ্ট্যের মানগুলির সাথে দৃষ্টান্তগুলির জন্য গুরুত্বপূর্ণ হতে পারে, যা রেফারেন্স চক্রের উদ্দেশ্য নয়। আপনার যদি কয়েক মিলিয়ন দৃষ্টান্ত তৈরি করতে হয় তবে এটি মেমরির ব্যবহার হ্রাস করতে সহায়তা করতে পারে। এখানে একটি উদাহরণস্বরূপ উদাহরণ


4
পছন্দ করি. 'এই লাইব্রেরিটি আসলে নামকরণের টিপলটির "পরিবর্তনীয়" বিকল্পের সমস্যার জন্য "ধারণার প্রমাণ"
আলেকজান্ডার

1
recordclassধীর হয়, আরো মেমরি লাগে, এবং হিসাবে সি-এক্সটেনশন প্রয়োজন তুলনায় Antti Haapala এর রেসিপি সঙ্গে namedlist
গ্রান্টজে

recordclassএটির collection.namedtupleএপিআই, মেমরির পদচিহ্ন, তবে সমর্থন কার্যভারগুলি উত্তরাধিকার সূত্রে প্রাপ্ত একটি পরিবর্তনীয় সংস্করণ । namedlistস্লট সহ পাইথন ক্লাসের প্রকৃত উদাহরণ। আপনার যদি সূচী অনুসারে এর ক্ষেত্রগুলিতে দ্রুত অ্যাক্সেসের প্রয়োজন না হয় তবে এটি আরও কার্যকর।
ইন্টেলিম্যাথ

recordclassউদাহরণস্বরূপ অ্যাট্রিবিউট অ্যাক্সেস (অজগর 3.5.2) এর তুলনায় প্রায় 2-3% ধীরnamedlist
ইন্টেলিম্যাথ

namedtupleসাধারণ শ্রেণি তৈরি এবং ব্যবহারের সময় Point = namedtuple('Point', 'x y'), জেদী বৈশিষ্ট্যগুলি স্বতঃপূরণ করতে পারে, যখন এটি ক্ষেত্রে হয় না recordclass। আমি যদি দীর্ঘতর কোড কোড ব্যবহার করি (ভিত্তিতে RecordClass) তবে জেদি Pointক্লাসটি বোঝে, তবে এর নির্মাতা বা বৈশিষ্ট্যগুলি নয় ... recordclassজেদির সাথে সুন্দরভাবে কাজ করার কোনও উপায় আছে কি ?
ফিলম্যাকেকে

34

প্রকারের.সিম্পলনেমস্পেসটি পাইথন ৩.৩ এ প্রবর্তিত হয়েছিল এবং অনুরোধকৃত প্রয়োজনীয়তা সমর্থন করে।

from types import SimpleNamespace
t = SimpleNamespace(foo='bar')
t.ham = 'spam'
print(t)
namespace(foo='bar', ham='spam')
print(t.foo)
'bar'
import pickle
with open('/tmp/pickle', 'wb') as f:
    pickle.dump(t, f)

1
আমি বছরের পর বছর ধরে এই জাতীয় কিছু খুঁজছি। ডটম্যাপের মতো একটি বিন্দুযুক্ত ডিক লাইব্রেরির জন্য দুর্দান্ত প্রতিস্থাপন
অ্যাক্সওয়েল

1
এটির জন্য আরও বেশি পরিমাণের প্রয়োজন। এটি ঠিক ওপি যা খুঁজছিল, এটি স্ট্যান্ডার্ড লাইব্রেরিতে রয়েছে এবং এটি ব্যবহার করা সহজ হতে পারে না। ধন্যবাদ!
টম জাইচ

3
-1 ওপি তার পরীক্ষাগুলির সাথে এটি খুব স্পষ্ট করে দিয়েছিল যেগুলি তার প্রয়োজনীয় SimpleNamespaceপরীক্ষাগুলি 6-10 (ইনডেক্স, অ্যাক্টিভেটরি আনপ্যাকিং, পুনরাবৃত্তি, আদেশযুক্ত ডিক, ইন-প্লেস রিপ্লেসমেন্ট) এবং 12, 13 (ক্ষেত্র, স্লট) দ্বারা অ্যাক্সেস করে tests নোট করুন যে ডকুমেন্টেশন (যা আপনি উত্তরে লিঙ্ক করেছেন) নির্দিষ্ট করে বলেছেন "এর SimpleNamespaceপ্রতিস্থাপন হিসাবে কার্যকর হতে পারে class NS: passHowever তবে namedtuple()পরিবর্তে কাঠামোগত রেকর্ড টাইপের ব্যবহারের জন্য ।"
আলী

1
-1 খুব, SimpleNamespaceএকটি অবজেক্ট তৈরি করে, ক্লাস কন্সট্রাক্টর নয়, এবং নেমটুপলের প্রতিস্থাপন হতে পারে না। প্রকার তুলনা কাজ করবে না এবং মেমরির পদচিহ্নগুলি আরও বেশি হবে।
রেডগ্লাইফ

26

পাইথন -৩.7 থেকে এই কাজটির জন্য পাইথোনিকের খুব বিকল্প হিসাবে আপনি dataclassesমডিউলটি ব্যবহার করতে পারেন যা কেবলমাত্র মিউটেবলের মতো আচরণ করে নাNamedTuple কারণ তারা সাধারণ বর্গ সংজ্ঞা ব্যবহার করে তারা অন্যান্য শ্রেণীর বৈশিষ্ট্যগুলিও সমর্থন করে।

পিইপি-0557 থেকে:

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

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

এই বৈশিষ্ট্যটি PEP-0557 এ চালু করা হয়েছে যা আপনি সরবরাহিত ডকুমেন্টেশন লিঙ্কে আরও বিশদে এটি সম্পর্কে পড়তে পারেন।

উদাহরণ:

In [20]: from dataclasses import dataclass

In [21]: @dataclass
    ...: class InventoryItem:
    ...:     '''Class for keeping track of an item in inventory.'''
    ...:     name: str
    ...:     unit_price: float
    ...:     quantity_on_hand: int = 0
    ...: 
    ...:     def total_cost(self) -> float:
    ...:         return self.unit_price * self.quantity_on_hand
    ...:    

ডেমো:

In [23]: II = InventoryItem('bisc', 2000)

In [24]: II
Out[24]: InventoryItem(name='bisc', unit_price=2000, quantity_on_hand=0)

In [25]: II.name = 'choco'

In [26]: II.name
Out[26]: 'choco'

In [27]: 

In [27]: II.unit_price *= 3

In [28]: II.unit_price
Out[28]: 6000

In [29]: II
Out[29]: InventoryItem(name='choco', unit_price=6000, quantity_on_hand=0)

1
এটি প্রয়োজনীয় ওপিতে পরীক্ষাগুলির সাথে খুব স্পষ্ট করে দেওয়া হয়েছিল এবং পরীক্ষাগুলিতে dataclassব্যর্থ হয় 6-10 (সূচী দ্বারা অ্যাক্সেস, পুনরায় পুনরুদ্ধার, পুনরাবৃত্তি, আদেশযুক্ত ডিক, স্থান প্রতিস্থাপন) এবং পাইথন ৩.7-এ 12, 13 (ক্ষেত্র, স্লট) .1।
আলী

1
যদিও এটি ওপি যা সন্ধান করছে তা সুনির্দিষ্টভাবে নাও হতে পারে, এটি অবশ্যই আমাকে সাহায্য করেছে :)
মার্টিন সিআর

25

সর্বশেষতম তালিকাভুক্ত তালিকা 1.7 11 জানুয়ারী, 2016 পর্যন্ত পাইথন 2.7 এবং পাইথন 3.5 উভয় দিয়ে আপনার সমস্ত পরীক্ষা পাস করে It এটি খাঁটি অজগর বাস্তবায়ন যেখানেrecordclass একটি সি এক্সটেনশান। অবশ্যই, এটি কোনও সি এক্সটেনশান অগ্রাধিকারপ্রাপ্ত কিনা তা আপনার প্রয়োজনীয়তার উপর নির্ভর করে।

আপনার পরীক্ষা (তবে নীচের নোটটি দেখুন):

from __future__ import print_function
import pickle
import sys
from namedlist import namedlist

Point = namedlist('Point', 'x y')
p = Point(x=1, y=2)

print('1. Mutation of field values')
p.x *= 10
p.y += 10
print('p: {}, {}\n'.format(p.x, p.y))

print('2. String')
print('p: {}\n'.format(p))

print('3. Representation')
print(repr(p), '\n')

print('4. Sizeof')
print('size of p:', sys.getsizeof(p), '\n')

print('5. Access by name of field')
print('p: {}, {}\n'.format(p.x, p.y))

print('6. Access by index')
print('p: {}, {}\n'.format(p[0], p[1]))

print('7. Iterative unpacking')
x, y = p
print('p: {}, {}\n'.format(x, y))

print('8. Iteration')
print('p: {}\n'.format([v for v in p]))

print('9. Ordered Dict')
print('p: {}\n'.format(p._asdict()))

print('10. Inplace replacement (update?)')
p._update(x=100, y=200)
print('p: {}\n'.format(p))

print('11. Pickle and Unpickle')
pickled = pickle.dumps(p)
unpickled = pickle.loads(pickled)
assert p == unpickled
print('Pickled successfully\n')

print('12. Fields\n')
print('p: {}\n'.format(p._fields))

print('13. Slots')
print('p: {}\n'.format(p.__slots__))

পাইথন ২.7 এ আউটপুট

ক্ষেত্রের মূল্যবোধের পরিবর্তন utation  
পি: 10, 12

2. স্ট্রিং  
পি: পয়েন্ট (x = 10, y = 12)

3. প্রতিনিধিত্ব  
পয়েন্ট (x = 10, y = 12) 

৪. আকার  
পি আকার: 64 

5. ক্ষেত্রের নাম দ্বারা অ্যাক্সেস  
পি: 10, 12

6. সূচক দ্বারা অ্যাক্সেস  
পি: 10, 12

7. Iterative আনপ্যাকিং  
পি: 10, 12

8. Iteration  
পি: [10, 12]

9. আদেশ ডিক্ট  
পি: অর্ডারডিক্ট ([('x', 10), ('y', 12)])

10. স্থান প্রতিস্থাপন (আপডেট?)  
পি: পয়েন্ট (x = 100, y = 200)

11. আচার এবং আনপিকল  
সফলভাবে উঠেছে

12. ক্ষেত্র  
পি: ('x', 'y')

13. স্লট  
পি: ('x', 'y')

পাইথন 3.5 এর সাথে একমাত্র পার্থক্য হ'ল namedlistআকারটি ছোট হয়েছে, আকারটি 56 (পাইথন ২. reports রিপোর্ট reports৪))

নোট করুন যে আমি জায়গাটিতে প্রতিস্থাপনের জন্য আপনার পরীক্ষা 10 পরিবর্তন করেছি। namedlistএকটি আছে _replace()পদ্ধতি যা অগভীর কপি করে, এবং কারণ যে আমার কাছে নিখুঁত জ্ঞান করে তোলে namedtupleমান লাইব্রেরিতে একই ভাবে আচরণ করে। _replace()পদ্ধতির শব্দার্থবিজ্ঞান পরিবর্তন বিভ্রান্তিকর হবে। আমার মতে _update()পদ্ধতিটি স্থানের আপডেটের জন্য ব্যবহার করা উচিত। অথবা আমি আপনার পরীক্ষার উদ্দেশ্য 10 বুঝতে ব্যর্থ হয়েছি?


গুরুত্বপূর্ণ অবহেলা আছে। namedlistস্টোর তালিকায় ইনস্ট্যান্সের মধ্যে সহকারে বিবেচনা করে। জিনিস যে cpythonএর listআসলে একটি গতিশীল অ্যারে। ডিজাইন অনুসারে, তালিকাটির পরিবর্তনকে আরও সস্তা করার জন্য এটি প্রয়োজনের চেয়ে বেশি মেমরি বরাদ্দ করে।
ইন্টেলিম্যাথ

1
@ ইনটেলিম্যাথ নামের তালিকাটি কিছুটা মিসনোমার। এটি আসলে উত্তরাধিকারসূত্রে আসে না listএবং ডিফল্টরূপে __slots__অপ্টিমাইজেশন ব্যবহার করে । যখন আমি পরিমাপ করেছি, মেমোরির ব্যবহার কম ছিল recordclass: পাইথন ২.7
গ্রান্টজে

@ গ্রান্টজে হ্যাঁ recorclassআরও মেমরি ব্যবহার করে কারণ এটি tupleভেরিয়েবল মেমরির আকারের সাথে একটি পছন্দসই বস্তু।
ইন্টিলিমাথ

2
নামবিহীন ডাউনভোটরা কাউকে সহায়তা করছে না। উত্তরে ভুল কী? ডাউনটা কেন?
আলী

আমি এটি টাইপসের বিরুদ্ধে সুরক্ষা পছন্দ করি যা এটি সম্মানের সাথে সরবরাহ করে types.SimpleNamespace। দুর্ভাগ্যক্রমে, পাইলট এটি পছন্দ করে না :-(
21:55

23

দেখে মনে হচ্ছে এই প্রশ্নের উত্তর নেই।

নীচে বেশ কাছাকাছি, কিন্তু এটি প্রযুক্তিগতভাবে পরিবর্তনযোগ্য নয়। এটি namedtuple()আপডেট হওয়া এক্স মান সহ একটি নতুন উদাহরণ তৈরি করছে :

Point = namedtuple('Point', ['x', 'y'])
p = Point(0, 0)
p = p._replace(x=10) 

অন্যদিকে, আপনি __slots__ক্লাস উদাহরণ বৈশিষ্ট্যগুলি ঘন ঘন আপডেট করার জন্য ভালভাবে কাজ করা উচিত এমন একটি সাধারণ ক্লাস তৈরি করতে পারেন :

class Point:
    __slots__ = ['x', 'y']
    def __init__(self, x, y):
        self.x = x
        self.y = y

এই উত্তরে যুক্ত করার জন্য, আমি __slots__এখানে ভাল ব্যবহার বলে মনে করি কারণ আপনি যখন প্রচুর শ্রেণীর উদাহরণ তৈরি করেন তখন এটি মেমরির দক্ষ। একমাত্র ক্ষতি হ'ল আপনি নতুন শ্রেণীর বৈশিষ্ট্য তৈরি করতে পারবেন না।

এখানে একটি প্রাসঙ্গিক থ্রেড যা মেমরির দক্ষতার চিত্রিত করে - অভিধান বনাম অবজেক্ট - যা আরও কার্যকর এবং কেন?

এই থ্রেডের উত্তরে উদ্ধৃত সামগ্রীটি একটি খুব সংক্ষিপ্ত ব্যাখ্যা যা কেন __slots__আরও মেমরি দক্ষ - পাইথন স্লট


1
বন্ধ, কিন্তু clunky। ধরা যাক আমি একটি + = অ্যাসাইনমেন্ট করতে চেয়েছিলাম, তখন আমার তা করা দরকার: p._replace (x = px + 10) বনাম px + = 10
আলেকজান্ডার

1
হ্যাঁ, এটি সত্যই বিদ্যমান
টিউপলটি

7

পাইথন 3 এর জন্য নিম্নলিখিতটি একটি ভাল সমাধান: নিম্নোক্ত ক্লাসটি ব্যবহার করে __slots__এবং Sequenceবিমূর্ত বেস শ্রেণীর; অভিনব ত্রুটি সনাক্তকরণ বা এই জাতীয় কাজ করে না, তবে এটি কাজ করে এবং বেশিরভাগ মিউটেটেবল টুপলের মতো আচরণ করে (টাইপেকেক বাদে)।

from collections import Sequence

class NamedMutableSequence(Sequence):
    __slots__ = ()

    def __init__(self, *a, **kw):
        slots = self.__slots__
        for k in slots:
            setattr(self, k, kw.get(k))

        if a:
            for k, v in zip(slots, a):
                setattr(self, k, v)

    def __str__(self):
        clsname = self.__class__.__name__
        values = ', '.join('%s=%r' % (k, getattr(self, k))
                           for k in self.__slots__)
        return '%s(%s)' % (clsname, values)

    __repr__ = __str__

    def __getitem__(self, item):
        return getattr(self, self.__slots__[item])

    def __setitem__(self, item, value):
        return setattr(self, self.__slots__[item], value)

    def __len__(self):
        return len(self.__slots__)

class Point(NamedMutableSequence):
    __slots__ = ('x', 'y')

উদাহরণ:

>>> p = Point(0, 0)
>>> p.x = 10
>>> p
Point(x=10, y=0)
>>> p.x *= 10
>>> p
Point(x=100, y=0)

আপনি যদি চান তবে আপনার ক্লাসটি তৈরি করার একটি পদ্ধতিও থাকতে পারে (যদিও একটি স্পষ্ট শ্রেণীর ব্যবহার আরও স্বচ্ছ):

def namedgroup(name, members):
    if isinstance(members, str):
        members = members.split()
    members = tuple(members)
    return type(name, (NamedMutableSequence,), {'__slots__': members})

উদাহরণ:

>>> Point = namedgroup('Point', ['x', 'y'])
>>> Point(6, 42)
Point(x=6, y=42)

পাইথন 2 এ আপনাকে এটি সামান্য সামঞ্জস্য করতে হবেSequence__dict__ - আপনি যদি উত্তরাধিকার সূত্রে উত্তীর্ণ হন তবে শ্রেণিতে একটি থাকবে এবং এটি __slots__কাজ করা বন্ধ করবে।

পাইথন 2 এর সমাধানটি উত্তরাধিকার সূত্রে প্রাপ্ত না হওয়া Sequence, তবে object। যদি isinstance(Point, Sequence) == Trueইচ্ছা হয় তবে আপনাকে NamedMutableSequenceবেস ক্লাস হিসাবে নিবন্ধকরণ করতে হবে Sequence:

Sequence.register(NamedMutableSequence)

3

গতিশীল টাইপ তৈরির সাথে এটি বাস্তবায়ন করা যাক:

import copy
def namedgroup(typename, fieldnames):

    def init(self, **kwargs): 
        attrs = {k: None for k in self._attrs_}
        for k in kwargs:
            if k in self._attrs_:
                attrs[k] = kwargs[k]
            else:
                raise AttributeError('Invalid Field')
        self.__dict__.update(attrs)

    def getattribute(self, attr):
        if attr.startswith("_") or attr in self._attrs_:
            return object.__getattribute__(self, attr)
        else:
            raise AttributeError('Invalid Field')

    def setattr(self, attr, value):
        if attr in self._attrs_:
            object.__setattr__(self, attr, value)
        else:
            raise AttributeError('Invalid Field')

    def rep(self):
         d = ["{}={}".format(v,self.__dict__[v]) for v in self._attrs_]
         return self._typename_ + '(' + ', '.join(d) + ')'

    def iterate(self):
        for x in self._attrs_:
            yield self.__dict__[x]
        raise StopIteration()

    def setitem(self, *args, **kwargs):
        return self.__dict__.__setitem__(*args, **kwargs)

    def getitem(self, *args, **kwargs):
        return self.__dict__.__getitem__(*args, **kwargs)

    attrs = {"__init__": init,
                "__setattr__": setattr,
                "__getattribute__": getattribute,
                "_attrs_": copy.deepcopy(fieldnames),
                "_typename_": str(typename),
                "__str__": rep,
                "__repr__": rep,
                "__len__": lambda self: len(fieldnames),
                "__iter__": iterate,
                "__setitem__": setitem,
                "__getitem__": getitem,
                }

    return type(typename, (object,), attrs)

ক্রিয়াকলাপ চালিয়ে যাওয়ার আগে তারা বৈধ কিনা তা দেখতে এটি বৈশিষ্ট্যগুলি পরীক্ষা করে।

তাহলে কি এই বাছাইযোগ্য? হ্যাঁ যদি (এবং কেবলমাত্র) আপনি নিম্নলিখিতটি করেন:

>>> import pickle
>>> Point = namedgroup("Point", ["x", "y"])
>>> p = Point(x=100, y=200)
>>> p2 = pickle.loads(pickle.dumps(p))
>>> p2.x
100
>>> p2.y
200
>>> id(p) != id(p2)
True

সংজ্ঞাটি আপনার নেমস্পেসে থাকতে হবে এবং আচার এটির জন্য এটি যথেষ্ট দীর্ঘ থাকতে হবে exist সুতরাং আপনি যদি এটি আপনার প্যাকেজে থাকতে সংজ্ঞা দেন তবে এটি কাজ করা উচিত।

Point = namedgroup("Point", ["x", "y"])

আপনি নিম্নলিখিতগুলি সম্পাদন করলে বা সংজ্ঞাটিকে অস্থায়ী করে তুললে আচার ব্যর্থ হবে (ফাংশন শেষ হয়ে গেলে সুযোগের বাইরে চলে যায়, বলুন):

some_point = namedgroup("Point", ["x", "y"])

এবং হ্যাঁ, এটি টাইপ তৈরির তালিকাভুক্ত ক্ষেত্রগুলির ক্রম সংরক্ষণ করে।


আপনি যদি এর __iter__সাথে কোনও পদ্ধতি যুক্ত করেন তবে for k in self._attrs_: yield getattr(self, k)এটি টিউলের মতো আনপ্যাকিং সমর্থন করবে।
স্ন্যাপশো

এছাড়া বেশ সহজ যোগ করার জন্য এর __len__, __getitem__এবং __setiem__পদ্ধতি মতো সূচক দ্বারা পেয়ে valus সমর্থন করার জন্য p[0]। এই শেষ বিটগুলির সাথে, এটি সর্বাধিক সম্পূর্ণ এবং সঠিক উত্তর বলে মনে হচ্ছে (যাই হোক আমার কাছে)।
স্ন্যাপশো

__len__এবং __iter__ভাল। __getitem__এবং __setitem__সত্যই ম্যাপ করা যায় self.__dict__.__setitem__এবংself.__dict__.__getitem__
MadMan2064

2

টিপলস সংজ্ঞা অনুসারে হয়।

তবে আপনি একটি অভিধান সাবক্লাস তৈরি করতে পারেন যেখানে আপনি বিন্দু-চিহ্ন সহ বৈশিষ্ট্যগুলি অ্যাক্সেস করতে পারেন;

In [1]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:class AttrDict(dict):
:
:    def __getattr__(self, name):
:        return self[name]
:
:    def __setattr__(self, name, value):
:        self[name] = value
:--

In [2]: test = AttrDict()

In [3]: test.a = 1

In [4]: test.b = True

In [5]: test
Out[5]: {'a': 1, 'b': True}

2

আপনি namedtuples কিন্তু চপল চেষ্টা হিসাবে অনুরূপ আচরণ চান namedlist

নোট করুন যে পরিবর্তনীয় হওয়ার জন্য এটি টিপল হতে পারে না


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

0

প্রদত্ত পারফরম্যান্সের খুব কম গুরুত্ব নেই, কেউ এর মতো মূর্খ হ্যাক ব্যবহার করতে পারে:

from collection import namedtuple

Point = namedtuple('Point', 'x y z')
mutable_z = Point(1,2,[3])

1
এই উত্তর খুব ভাল ব্যাখ্যা করা হয় নি। আপনি তালিকার পরিবর্তনীয় প্রকৃতি বুঝতে না পারলে এটি বিভ্রান্তিকর দেখাচ্ছে। --- এই উদাহরণে ... পুনরায় নিয়োগের জন্য z, আপনাকে mutable_z.z.pop(0)তখন কল করতে হবে mutable_z.z.append(new_value)। যদি আপনি এই ভুলটি পান তবে আপনার 1 টিরও বেশি উপাদান শেষ হবে এবং আপনার প্রোগ্রামটি অপ্রত্যাশিতভাবে আচরণ করবে।
বাইকসর

1
@byxor, অথবা আপনি শুধু করতে পারে: mutable_z.z[0] = newValue। এটি প্রকৃতপক্ষে একটি হ্যাক, যেমনটি বলা হয়েছে।
এসআরজি

হ্যাঁ, আমি অবাক হয়েছি আমি এটি পুনরায় বরাদ্দ করার আরও সুস্পষ্ট উপায়টি মিস করেছি।
বাইজোর

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