पर्ल में 'मेरे' और 'हमारे' में क्या अंतर है?


188

मुझे पता है कि myपर्ल में क्या है। यह एक चर को परिभाषित करता है जो केवल उस खंड के दायरे में मौजूद है जिसमें इसे परिभाषित किया गया है। क्या करता ourहै?

कैसे ourअलग है my?

जवाबों:


215

महान सवाल: कैसे ourअलग है myऔर क्या करता ourहै?

संक्षेप में:

पर्ल 5 के बाद से उपलब्ध, myगैर-पैकेज चर घोषित करने का एक तरीका है, जो हैं:

  • निजी
  • नया
  • गैर-वैश्विक
  • किसी भी पैकेज से अलग, ताकि चर के रूप में पहुँचा नहीं जा सके $package_name::variable


दूसरी ओर, ourचर पैकेज चर हैं, और इस प्रकार स्वचालित रूप से:

  • वैश्विक चर
  • निश्चित रूप से निजी नहीं
  • जरूरी नहीं कि नया हो
  • योग्य नाम स्थान के साथ पैकेज (या लेक्सिकल स्कोप) के बाहर पहुँचा जा सकता है, जैसा कि $package_name::variable


एक चर की घोषणा के साथ ourआप use strictटाइपो चेतावनियों या संकलन-समय त्रुटियों को प्राप्त किए बिना उन्हें उपयोग करने के लिए चर को पूर्वनिर्धारित करने की अनुमति देता है । पर्ल 5.6 के बाद से, इसने अप्रचलित को बदल दिया है use vars, जो केवल फ़ाइल-स्कॉप्ड था, और जैसा कि वैसा ही नहीं है our

उदाहरण के लिए, चर के लिए औपचारिक, योग्य नाम $xके अंदर package mainहै $main::x। घोषणा our $xकरने से आपको $xदंड के बिना नंगे चर का उपयोग करने की अनुमति मिलती है (यानी, परिणामस्वरूप त्रुटि के बिना), घोषणा के दायरे में, जब स्क्रिप्ट का उपयोग होता है use strictया use strict "vars"। गुंजाइश एक, या दो, या अधिक पैकेज, या एक छोटा ब्लॉक हो सकता है।


2
तो हमारा स्थानीय से अलग कैसे है?
नाथन फेलमैन

17
@ नथन फेलमैन, localचर नहीं बनाते हैं। यह से संबंधित नहीं है myऔर ourसब पर। localअस्थायी रूप से चर के मूल्य का समर्थन करता है और इसके वर्तमान मूल्य को साफ करता है।
इकेगामी

1
ourचर पैकेज चर नहीं हैं। वे वैश्विक रूप से स्कोप्ड नहीं हैं, लेकिन लेक्सिकली-स्कॉप्ड वैरिएबल जैसे myवैरिएबल हैं। आप इसे निम्नलिखित कार्यक्रम में देख सकते हैं package Foo; our $x = 123; package Bar; say $x;:। यदि आप एक पैकेज चर को "घोषित" करना चाहते हैं, तो आपको उपयोग करने की आवश्यकता है use vars qw( $x );our $x;एक लेक्सिकली-स्कोपेड वैरिएबल घोषित करता है जो पैकेज में उसी नाम वाले वैरिएबल से अलियास किया गया है जिसमें ourसंकलित किया गया था।
इकेगामी

60

कार्टमैन और ओलाफुर के पेरलोनॉक्स और पर्लडॉक लिंक एक महान संदर्भ हैं - नीचे एक सारांश में मेरी दरार है:

myचर एक ही ब्लॉक द्वारा {}या एक ही फाइल के भीतर परिभाषित नहीं तो अगर {}एस में नहीं हैं । वे समान लेक्सिकल स्कोप / ब्लॉक के बाहर परिभाषित पैकेज / सबरूटीन से सुलभ नहीं हैं।

ourचर एक पैकेज / फ़ाइल के भीतर बंद कर दिए जाते हैं और किसी भी कोड से useया requireउस पैकेज / फ़ाइल से पहुंच योग्य होते हैं - उचित नामस्थान को प्रीपे करके संकुल के बीच नाम संघर्षों को हल किया जाता है।

बस इसे गोल करने के लिए, localवैरिएबल को "डायनामिक रूप से" स्कूप किया गया है, myवैरिएबल से अलग है कि वे उसी ब्लॉक के भीतर कहे जाने वाले सबरूटीन से भी सुलभ हैं।


+1 के लिए " myवैरिएबल लेक्सिकली स्कॉप्ड हैं [...] उसी फाइल के भीतर यदि {}s में नहीं है "। यह मेरे लिए उपयोगी था, धन्यवाद।
जॉर्ज

48

एक उदाहरण:

use strict;

for (1 .. 2){
    # Both variables are lexically scoped to the block.
    our ($o);  # Belongs to 'main' package.
    my  ($m);  # Does not belong to a package.

    # The variables differ with respect to newness.
    $o ++;
    $m ++;
    print __PACKAGE__, " >> o=$o m=$m\n";  # $m is always 1.

    # The package has changed, but we still have direct,
    # unqualified access to both variables, because the
    # lexical scope has not changed.
    package Fubb;
    print __PACKAGE__, " >> o=$o m=$m\n";
}

# The our() and my() variables differ with respect to privacy.
# We can still access the variable declared with our(), provided
# that we fully qualify its name, but the variable declared
# with my() is unavailable.
print __PACKAGE__, " >> main::o=$main::o\n";  # 2
print __PACKAGE__, " >> main::m=$main::m\n";  # Undefined.

# Attempts to access the variables directly won't compile.
# print __PACKAGE__, " >> o=$o\n";
# print __PACKAGE__, " >> m=$m\n";

# Variables declared with use vars() are like those declared
# with our(): belong to a package; not private; and not new.
# However, their scoping is package-based rather than lexical.
for (1 .. 9){
    use vars qw($uv);
    $uv ++;
}

# Even though we are outside the lexical scope where the
# use vars() variable was declared, we have direct access
# because the package has not changed.
print __PACKAGE__, " >> uv=$uv\n";

# And we can access it from another package.
package Bubb;
print __PACKAGE__, " >> main::uv=$main::uv\n";

11

स्कूपिंग के साथ नकल पर्ल स्कूपिंग नियमों का एक अच्छा अवलोकन है। यह काफी पुराना है जिसकी ourचर्चा पाठ के मुख्य भाग में नहीं की गई है। इसे अंत में नोट्स सेक्शन में संबोधित किया जाता है ।

आलेख पैकेज चर और डायनेमिक स्कोप के बारे में बात करता है और यह कैसे लेक्सिकल वैरिएबल और लेक्सिकल स्कोप से भिन्न होता है।


5

myका उपयोग स्थानीय चर के लिए किया जाता है, जबकि ourवैश्विक चर के लिए उपयोग किया जाता है।

पर्ल में वैरिएबल स्कोपिंग पर अधिक पढ़ना : मूल बातें


16
स्थानीय और वैश्विक शब्दों के आसपास टॉस करने से सावधान रहें। उचित शब्द शाब्दिक और पैकेज हैं। आप पर्ल में वास्तविक वैश्विक चर नहीं बना सकते हैं, लेकिन कुछ पहले से ही $ _ की तरह मौजूद हैं, और स्थानीय रूप से स्थानीय मानों (स्थानीय द्वारा निर्मित) के साथ पैकेज चर को संदर्भित करता है, न कि शाब्दिक चर (मेरे साथ बनाया) को।
चास। ओवेन्स

${^Potato}वैश्विक है। यह उसी चर को संदर्भित करता है जहां आप इसका उपयोग करते हैं।
MJD

5

मैंने कभी पर्ल में कुछ शाब्दिक घोषणाओं के बारे में मुलाकात की, जिसने मुझे गड़बड़ कर दिया, जो इस प्रश्न से भी संबंधित हैं, इसलिए मैं यहां अपना सारांश जोड़ता हूं:

1. परिभाषा या घोषणा?

local $var = 42;
print "var: $var\n";

आउटपुट है var: 42। हालांकि हम यह नहीं बता सकते कि local $var = 42;परिभाषा या घोषणा है। लेकिन इस बारे में कैसे:

use strict;
use warnings;

local $var = 42;
print "var: $var\n";

दूसरा प्रोग्राम एक त्रुटि फेंक देगा:

Global symbol "$var" requires explicit package name.

$varपरिभाषित नहीं है, जिसका अर्थ है local $var;कि सिर्फ एक घोषणा! localएक चर घोषित करने का उपयोग करने से पहले , सुनिश्चित करें कि इसे पहले एक वैश्विक चर के रूप में परिभाषित किया गया है।

लेकिन यह असफल क्यों नहीं होगा?

use strict;
use warnings;

local $a = 42;
print "var: $a\n";

उत्पादन होता है: var: 42

ऐसा इसलिए है $a, क्योंकि साथ ही $b, पर्ल में पूर्व-परिभाषित एक वैश्विक चर है। सॉर्ट फ़ंक्शन याद है ?

2. लेक्सिकल या ग्लोबल?

मैं पर्ल का उपयोग शुरू करने से पहले एक सी प्रोग्रामर था, इसलिए शाब्दिक और वैश्विक चर की अवधारणा मुझे सीधी लगती है: यह सिर्फ सी में ऑटो और बाहरी चर से मेल खाती है लेकिन छोटे अंतर हैं:

सी में, एक बाहरी चर किसी भी फ़ंक्शन ब्लॉक के बाहर परिभाषित एक चर है। दूसरी ओर, एक स्वचालित चर एक फ़ंक्शन ब्लॉक के अंदर परिभाषित एक चर है। ऐशे ही:

int global;

int main(void) {
    int local;
}

पर्ल में रहते हुए, चीजें सूक्ष्म हैं:

sub main {
    $var = 42;
}

&main;

print "var: $var\n";

आउटपुट है var: 42$varभले ही यह फ़ंक्शन ब्लॉक में परिभाषित किया गया हो, एक वैश्विक चर है! दरअसल पर्ल में, किसी भी चर को डिफ़ॉल्ट रूप से वैश्विक घोषित किया जाता है।

सबक हमेशा use strict; use warnings;एक पर्ल प्रोग्राम की शुरुआत में जोड़ना है , जो प्रोग्रामर को शाब्दिक चर को स्पष्ट रूप से घोषित करने के लिए मजबूर करेगा, ताकि हमें दी गई कुछ गलतियों से गड़बड़ न हो।


यहां पर ["याद रखना [$ a और $ b in] छाँटना"] ( stackoverflow.com/a/26128328/1028230 )। पर्ल कभी नहीं रुकता, उम, मुझे अचरज करो।
रफिन

4

Perldoc हमारे की एक अच्छी परिभाषा है।

मेरे विपरीत, जो दोनों एक चर के लिए भंडारण को आवंटित करता है और वर्तमान गुंजाइश के भीतर उपयोग के लिए उस भंडारण के साथ एक साधारण नाम को जोड़ता है, हमारे सहयोगी वर्तमान पैकेज में पैकेज चर के साथ एक साधारण नाम को वर्तमान दायरे के भीतर उपयोग के लिए जोड़ते हैं। दूसरे शब्दों में, हमारे पास मेरे समान ही नियम हैं, लेकिन जरूरी नहीं कि एक चर बनाया जाए।


2

यह केवल कुछ हद तक प्रश्न से संबंधित है, लेकिन मैंने अभी एक (मेरे लिए) पर्ल सिंटैक्स की अस्पष्ट बिट की खोज की है जिसे आप "हमारे" (पैकेज) चर के साथ उपयोग कर सकते हैं जिसे आप "मेरे" (स्थानीय) के साथ उपयोग नहीं कर सकते हैं चर।

#!/usr/bin/perl

our $foo = "BAR";

print $foo . "\n";
${"foo"} = "BAZ";
print $foo . "\n";

आउटपुट:

BAR
BAZ

यदि आप 'हमारे' को 'मेरे' में बदलते हैं तो यह काम नहीं करेगा।


1
ऐसा नहीं। $ foo $ {foo} $ {'foo'} $ {"foo"} सभी चर असाइनमेंट या डेरेफ़रिंग के लिए समान कार्य करते हैं। मेरे काम के लिए उपरोक्त उदाहरण में हमारी अदला-बदली । जो आपने शायद अनुभव किया था वह पैकेज चर के रूप में $ foo को कम करने की कोशिश कर रहा था, जैसे $ मुख्य :: फू या $ :: फू जो केवल पैकेज ग्लोबल्स के लिए काम करेगा, जैसे कि हमारे साथ परिभाषित ।
कॉस्मिकनेट

बस v5.20 का उपयोग करके सेवानिवृत्त, और यह निश्चित रूप से मेरे साथ एक ही आउटपुट नहीं देता है (यह बार बार प्रिंट करता है।)
मिशा गेल

1
मेरा परीक्षण (विंडोज़ पर): perl -e "my $foo = 'bar'; print $foo; ${foo} = 'baz'; pr int $foo"आउटपुट: barbaz perl -e "my $foo = 'bar'; print $foo; ${"foo"} = 'baz'; print $foo"आउटपुट: barbaz perl -e "my $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"आउटपुट: barbar तो मेरे परीक्षण में मैं एक ही जाल में गिर गया। $ {foo} $ foo के समान है, कोष्ठक प्रक्षेप करते समय उपयोगी होते हैं। $ {"foo"} वास्तव में $ main :: {} पर एक नज़र है जो मुख्य प्रतीक तालिका है, जैसे कि केवल पैकेज स्कूप्ड चर होते हैं।
कॉस्मिकनेट

1
$ {"मुख्य :: फू"}, $ {":: फू"}, और $ मुख्य :: फू $ {"फू"} के समान हैं। आशुलिपि पैकेज संवेदनशील perl -e "package test; our $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"कार्य है, इस संदर्भ में $ {"फू"} अब $ {"परीक्षण :: फू"} के बराबर है। प्रतीक चिह्न और ग्लोब के बारे में कुछ जानकारी है, जैसा कि एडवांस्ड पर्ल प्रोग्रामिंग बुक करती है। मेरी पिछली गलती के लिए क्षमा करें।
कॉस्मिकनेट

0
print "package is: " . __PACKAGE__ . "\n";
our $test = 1;
print "trying to print global var from main package: $test\n";

package Changed;

{
        my $test = 10;
        my $test1 = 11;
        print "trying to print local vars from a closed block: $test, $test1\n";
}

&Check_global;

sub Check_global {
        print "trying to print global var from a function: $test\n";
}
print "package is: " . __PACKAGE__ . "\n";
print "trying to print global var outside the func and from \"Changed\" package:     $test\n";
print "trying to print local var outside the block $test1\n";

इसे आउटपुट करेंगे:

package is: main
trying to print global var from main package: 1
trying to print local vars from a closed block: 10, 11
trying to print global var from a function: 1
package is: Changed
trying to print global var outside the func and from "Changed" package: 1
trying to print local var outside the block 

स्क्रिप्ट का उपयोग करने का प्रयास करते समय "सख्त का उपयोग करें" इस मामले में विफलता मिलेगी:

Global symbol "$test1" requires explicit package name at ./check_global.pl line 24.
Execution of ./check_global.pl aborted due to compilation errors.

कृपया किसी प्रकार का स्पष्टीकरण प्रदान करें। इस तरह का डंपिंग कोड शायद ही कभी उचित माना जाता है।
स्कॉट सोमर

सरल शब्दों में: हमारी (जैसा कि नाम साइस) स्क्रिप्ट में किसी भी स्थान से उस वेरिएबल का उपयोग करने की एक परिवर्तनीय घोषणा है (फ़ंक्शन, ब्लॉक आदि ...), डिफ़ॉल्ट रूप से (घोषित नहीं होने पर) हर चर "मुख्य" से संबंधित होता है पैकेज, हमारे चर अभी भी स्क्रिप्ट में एक और पैकेज की घोषणा के बाद भी इस्तेमाल किया जा सकता है। किसी ब्लॉक या फ़ंक्शन में घोषित "मेरा" वेरिएबल का उपयोग केवल उस ब्लॉक / फ़ंक्शन में किया जा सकता है। यदि "मेरे" वैरिएबल को किसी ब्लॉक में बंद नहीं घोषित किया गया था, तो इसका उपयोग किसी भी स्क्राइबर में, जहाँ एक बंद ब्लॉक में या किसी फ़ंक्शन में "हमारे" वेरिएबल के रूप में किया जा सकता है, लेकिन केस पैकेज में उपयोग नहीं किया जा सकता है
लवी बुचनिक

ऊपर मेरी स्क्रिप्ट से पता चलता है कि डिफ़ॉल्ट रूप से हम "मुख्य" पैकेज में हैं, तो स्क्रिप्ट "मुख्य" पैकेज से "हमारे" चर को प्रिंट करती है (ब्लॉक में बंद नहीं), फिर हम एक फ़ंक्शन में दो "मेरे" चर घोषित करते हैं और उन्हें उस फ़ंक्शन से प्रिंट करें। फिर हम एक अन्य फ़ंक्शन से "हमारा" वेरिएबल प्रिंट करते हैं, यह दिखाने के लिए कि इसे किसी फ़ंक्शन में उपयोग किया जा सकता है। फिर हम पैकेज को "परिवर्तित" (नहीं "मुख्य" नहीं और अधिक) बदल रहे हैं, और हम फिर से "हमारे" चर को सफलतापूर्वक प्रिंट करते हैं। तब फ़ंक्शन के बाहर एक "मेरा" चर प्रिंट करने की कोशिश कर रहा था और विफल रहा। स्क्रिप्ट केवल "हमारे" और "मेरे" उपयोग के बीच अंतर दिखा रही है।
Lavi Buchnik

0

बस निम्नलिखित कार्यक्रम का उपयोग करने का प्रयास करें:

#!/usr/local/bin/perl
use feature ':5.10';
#use warnings;
package a;
{
my $b = 100;
our $a = 10;


print "$a \n";
print "$b \n";
}

package b;

#my $b = 200;
#our $a = 20 ;

print "in package b value of  my b $a::b \n";
print "in package b value of our a  $a::a \n";

यह मेरे और हमारे बीच का अंतर बताता है। मेरा चर घुंघराले ब्रेस के बाहर दायरे से बाहर चला जाता है और कचरा एकत्र किया जाता है लेकिन हमारा चर अभी भी रहता है।
युगदेव

-1
#!/usr/bin/perl -l

use strict;

# if string below commented out, prints 'lol' , if the string enabled, prints 'eeeeeeeee'
#my $lol = 'eeeeeeeeeee' ;
# no errors or warnings at any case, despite of 'strict'

our $lol = eval {$lol} || 'lol' ;

print $lol;

क्या आप बता सकते हैं कि यह कोड प्रदर्शित करने के लिए क्या है? अलग ourऔर myअलग क्यों हैं ? यह उदाहरण कैसे दिखाता है?
नाथन फेलमैन

-1

हमें लगता है कि वास्तव में एक दुभाषिया क्या है: यह कोड का एक टुकड़ा है जो स्मृति में मूल्यों को संग्रहीत करता है और एक प्रोग्राम में निर्देश देता है कि यह उन मूल्यों को उनके नामों तक पहुंच प्रदान करता है, जो इन निर्देशों के अंदर निर्दिष्ट हैं। तो, एक दुभाषिया का बड़ा काम नियमों को आकार देना है कि हम उन निर्देशों में नामों का उपयोग कैसे करें, जो दुभाषिया स्टोर करता है।

"मेरे" का सामना करने पर, दुभाषिया एक शाब्दिक चर बनाता है: एक नामित मूल्य जो दुभाषिया केवल तब तक पहुंच सकता है जब यह एक ब्लॉक निष्पादित करता है, और केवल उस वाक्यविन्यास ब्लॉक के भीतर से। "हमारे" का सामना करने पर, दुभाषिया पैकेज चर का एक शाब्दिक उपनाम बनाता है: यह एक नाम को बांधता है, जिसे दुभाषिया माना जाता है तब से एक शाब्दिक चर के नाम के रूप में संसाधित होने तक, ब्लॉक के समाप्त होने तक, पैकेज के मूल्य तक एक ही नाम के साथ चर।

इसका प्रभाव यह है कि आप तब दिखावा कर सकते हैं कि आप एक शाब्दिक चर का उपयोग कर रहे हैं और पैकेज चर की पूरी योग्यता पर 'सख्त उपयोग' के नियमों को दरकिनार कर रहे हैं। चूंकि दुभाषिया स्वचालित रूप से पैकेज चर बनाता है जब वे पहली बार उपयोग किए जाते हैं, "हमारे" का उपयोग करने का दुष्प्रभाव यह भी हो सकता है कि दुभाषिया एक पैकेज चर भी बनाता है। इस मामले में, दो चीजें बनाई जाती हैं: एक पैकेज चर, जिसे दुभाषिया हर जगह से एक्सेस कर सकता है, बशर्ते वह ठीक से नामित हो, जैसा कि 'सख्त उपयोग' (इसके पैकेज और दो कॉलन के नाम से पहले से), और इसके शाब्दिक उपनाम से अनुरोध किया गया है ।

सूत्रों का कहना है:

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.